[libvirt] [PATCH V2 0/4] Xen-xl parser

Kiarie Kahurani (4): src/xenconfig: Export helper functions src/xenconfig: Xen-xl parser src/xenconfig: Introduce xen-xl on virsh command line tests: Tests for the xen-xl parser configure.ac | 7 + src/Makefile.am | 21 +- src/libvirt_xenconfig.syms | 4 + src/libxl/libxl_driver.c | 46 +++- src/xenconfig/libxlu_disk_i.h | 28 ++ src/xenconfig/libxlu_disk_l.l | 259 +++++++++++++++++++ src/xenconfig/xen_common.c | 147 +++++------ src/xenconfig/xen_common.h | 24 +- src/xenconfig/xen_xl.c | 479 +++++++++++++++++++++++++++++++++++ src/xenconfig/xen_xl.h | 29 +++ tests/Makefile.am | 9 +- tests/testutilsxen.c | 50 ++++ tests/testutilsxen.h | 9 +- tests/xlconfigdata/test-new-disk.cfg | 27 ++ tests/xlconfigdata/test-new-disk.xml | 45 ++++ tests/xlconfigdata/test-spice.cfg | 32 +++ tests/xlconfigdata/test-spice.xml | 45 ++++ tests/xlconfigtest.c | 224 ++++++++++++++++ 18 files changed, 1389 insertions(+), 96 deletions(-) create mode 100644 src/xenconfig/libxlu_disk_i.h create mode 100644 src/xenconfig/libxlu_disk_l.l 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 Changes in V1 -introduced flex for xl disk format parsing Changes in V2 -changed ot use AC_PROG_LEX in configure.ac -got rid of unused data files Not done -compile the generated file using global compiler flags as it has unused parameters -- 1.8.4.5

Export helper function for reuse in getting values from a virConfPtr object Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> --- src/xenconfig/xen_common.c | 144 ++++++++++++++++++++++----------------------- src/xenconfig/xen_common.h | 24 ++++++-- 2 files changed, 91 insertions(+), 77 deletions(-) diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 9beaf6c..d71dd07 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -43,7 +43,7 @@ /* * Convenience method to grab a long int from the config file object */ -static int +int xenConfigGetBool(virConfPtr conf, const char *name, int *value, @@ -73,7 +73,7 @@ xenConfigGetBool(virConfPtr conf, /* * Convenience method to grab a int from the config file object */ -static int +int xenConfigGetULong(virConfPtr conf, const char *name, unsigned long *value, @@ -179,7 +179,7 @@ xenConfigCopyString(virConfPtr conf, const char *name, char **value) } -static int +int xenConfigCopyStringOpt(virConfPtr conf, const char *name, char **value) { return xenConfigCopyStringInternal(conf, name, value, 1); @@ -262,8 +262,8 @@ xenConfigGetString(virConfPtr conf, } -static int -xenXMConfigSetInt(virConfPtr conf, const char *setting, long long l) +int +xenConfigSetInt(virConfPtr conf, const char *setting, long long l) { virConfValuePtr value = NULL; @@ -283,8 +283,8 @@ xenXMConfigSetInt(virConfPtr conf, const char *setting, long long l) } -static int -xenXMConfigSetString(virConfPtr conf, const char *setting, const char *str) +int +xenConfigSetString(virConfPtr conf, const char *setting, const char *str) { virConfValuePtr value = NULL; @@ -1387,11 +1387,11 @@ xenFormatGeneralMeta(virConfPtr conf, virDomainDefPtr def) { char uuid[VIR_UUID_STRING_BUFLEN]; - if (xenXMConfigSetString(conf, "name", def->name) < 0) + if (xenConfigSetString(conf, "name", def->name) < 0) return -1; virUUIDFormat(def->uuid, uuid); - if (xenXMConfigSetString(conf, "uuid", uuid) < 0) + if (xenConfigSetString(conf, "uuid", uuid) < 0) return -1; return 0; @@ -1401,12 +1401,12 @@ xenFormatGeneralMeta(virConfPtr conf, virDomainDefPtr def) static int xenFormatMem(virConfPtr conf, virDomainDefPtr def) { - if (xenXMConfigSetInt(conf, "maxmem", - VIR_DIV_UP(def->mem.max_balloon, 1024)) < 0) + if (xenConfigSetInt(conf, "maxmem", + VIR_DIV_UP(def->mem.max_balloon, 1024)) < 0) return -1; - if (xenXMConfigSetInt(conf, "memory", - VIR_DIV_UP(def->mem.cur_balloon, 1024)) < 0) + if (xenConfigSetInt(conf, "memory", + VIR_DIV_UP(def->mem.cur_balloon, 1024)) < 0) return -1; return 0; @@ -1468,7 +1468,7 @@ xenFormatTimeOffset(virConfPtr conf, virDomainDefPtr def, int xendConfigVersion) virDomainClockOffsetTypeToString(def->clock.offset)); return -1; } - if (xenXMConfigSetInt(conf, "rtc_timeoffset", rtc_timeoffset) < 0) + if (xenConfigSetInt(conf, "rtc_timeoffset", rtc_timeoffset) < 0) return -1; } else { @@ -1489,7 +1489,7 @@ xenFormatTimeOffset(virConfPtr conf, virDomainDefPtr def, int xendConfigVersion) } /* !hvm */ } - if (xenXMConfigSetInt(conf, "localtime", vmlocaltime) < 0) + if (xenConfigSetInt(conf, "localtime", vmlocaltime) < 0) return -1; return 0; @@ -1506,7 +1506,7 @@ xenFormatEventActions(virConfPtr conf, virDomainDefPtr def) _("unexpected lifecycle action %d"), def->onPoweroff); return -1; } - if (xenXMConfigSetString(conf, "on_poweroff", lifecycle) < 0) + if (xenConfigSetString(conf, "on_poweroff", lifecycle) < 0) return -1; @@ -1515,7 +1515,7 @@ xenFormatEventActions(virConfPtr conf, virDomainDefPtr def) _("unexpected lifecycle action %d"), def->onReboot); return -1; } - if (xenXMConfigSetString(conf, "on_reboot", lifecycle) < 0) + if (xenConfigSetString(conf, "on_reboot", lifecycle) < 0) return -1; @@ -1524,7 +1524,7 @@ xenFormatEventActions(virConfPtr conf, virDomainDefPtr def) _("unexpected lifecycle action %d"), def->onCrash); return -1; } - if (xenXMConfigSetString(conf, "on_crash", lifecycle) < 0) + if (xenConfigSetString(conf, "on_crash", lifecycle) < 0) return -1; return 0; @@ -1545,12 +1545,12 @@ xenFormatCharDev(virConfPtr conf, virDomainDefPtr def) ret = xenFormatSxprChr(def->parallels[0], &buf); str = virBufferContentAndReset(&buf); if (ret == 0) - ret = xenXMConfigSetString(conf, "parallel", str); + ret = xenConfigSetString(conf, "parallel", str); VIR_FREE(str); if (ret < 0) return -1; } else { - if (xenXMConfigSetString(conf, "parallel", "none") < 0) + if (xenConfigSetString(conf, "parallel", "none") < 0) return -1; } @@ -1563,7 +1563,7 @@ xenFormatCharDev(virConfPtr conf, virDomainDefPtr def) ret = xenFormatSxprChr(def->serials[0], &buf); str = virBufferContentAndReset(&buf); if (ret == 0) - ret = xenXMConfigSetString(conf, "serial", str); + ret = xenConfigSetString(conf, "serial", str); VIR_FREE(str); if (ret < 0) return -1; @@ -1608,7 +1608,7 @@ xenFormatCharDev(virConfPtr conf, virDomainDefPtr def) VIR_FREE(serialVal); } } else { - if (xenXMConfigSetString(conf, "serial", "none") < 0) + if (xenConfigSetString(conf, "serial", "none") < 0) return -1; } } @@ -1623,13 +1623,13 @@ xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def) int ret = -1; char *cpus = NULL; - if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0) + if (xenConfigSetInt(conf, "vcpus", def->maxvcpus) < 0) goto cleanup; /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is either 32, or 64 on a platform where long is big enough. */ if (def->vcpus < def->maxvcpus && - xenXMConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0) + xenConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0) goto cleanup; if ((def->cpumask != NULL) && @@ -1638,7 +1638,7 @@ xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def) } if (cpus && - xenXMConfigSetString(conf, "cpus", cpus) < 0) + xenConfigSetString(conf, "cpus", cpus) < 0) goto cleanup; ret = 0; @@ -1655,37 +1655,37 @@ xenFormatCPUFeatures(virConfPtr conf, virDomainDefPtr def, int xendConfigVersion size_t i; if (STREQ(def->os.type, "hvm")) { - if (xenXMConfigSetInt(conf, "pae", - (def->features[VIR_DOMAIN_FEATURE_PAE] == - VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) + if (xenConfigSetInt(conf, "pae", + (def->features[VIR_DOMAIN_FEATURE_PAE] == + VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; - if (xenXMConfigSetInt(conf, "acpi", - (def->features[VIR_DOMAIN_FEATURE_ACPI] == - VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) + if (xenConfigSetInt(conf, "acpi", + (def->features[VIR_DOMAIN_FEATURE_ACPI] == + VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; - if (xenXMConfigSetInt(conf, "apic", - (def->features[VIR_DOMAIN_FEATURE_APIC] == - VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) + if (xenConfigSetInt(conf, "apic", + (def->features[VIR_DOMAIN_FEATURE_APIC] == + VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; if (xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4) { - if (xenXMConfigSetInt(conf, "hap", - (def->features[VIR_DOMAIN_FEATURE_HAP] == - VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) + if (xenConfigSetInt(conf, "hap", + (def->features[VIR_DOMAIN_FEATURE_HAP] == + VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; - if (xenXMConfigSetInt(conf, "viridian", - (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == - VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) + if (xenConfigSetInt(conf, "viridian", + (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == + VIR_TRISTATE_SWITCH_ON) ? 1 : 0) < 0) return -1; } for (i = 0; i < def->clock.ntimers; i++) { if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET && def->clock.timers[i]->present != -1 && - xenXMConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) + xenConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0) return -1; } } @@ -1698,7 +1698,7 @@ static int xenFormatEmulator(virConfPtr conf, virDomainDefPtr def) { if (def->emulator && - xenXMConfigSetString(conf, "device_model", def->emulator) < 0) + xenConfigSetString(conf, "device_model", def->emulator) < 0) return -1; return 0; @@ -1717,7 +1717,7 @@ xenFormatCDROM(virConfPtr conf, virDomainDefPtr def, int xendConfigVersion) def->disks[i]->dst && STREQ(def->disks[i]->dst, "hdc") && virDomainDiskGetSource(def->disks[i])) { - if (xenXMConfigSetString(conf, "cdrom", + if (xenConfigSetString(conf, "cdrom", virDomainDiskGetSource(def->disks[i])) < 0) return -1; break; @@ -1737,11 +1737,11 @@ xenFormatOS(virConfPtr conf, virDomainDefPtr def) if (STREQ(def->os.type, "hvm")) { char boot[VIR_DOMAIN_BOOT_LAST+1]; - if (xenXMConfigSetString(conf, "builder", "hvm") < 0) + if (xenConfigSetString(conf, "builder", "hvm") < 0) return -1; if (def->os.loader && - xenXMConfigSetString(conf, "kernel", def->os.loader) < 0) + xenConfigSetString(conf, "kernel", def->os.loader) < 0) return -1; for (i = 0; i < def->os.nBootDevs; i++) { @@ -1769,29 +1769,29 @@ xenFormatOS(virConfPtr conf, virDomainDefPtr def) boot[def->os.nBootDevs] = '\0'; } - if (xenXMConfigSetString(conf, "boot", boot) < 0) + if (xenConfigSetString(conf, "boot", boot) < 0) return -1; /* XXX floppy disks */ } else { if (def->os.bootloader && - xenXMConfigSetString(conf, "bootloader", def->os.bootloader) < 0) + xenConfigSetString(conf, "bootloader", def->os.bootloader) < 0) return -1; if (def->os.bootloaderArgs && - xenXMConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0) + xenConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0) return -1; if (def->os.kernel && - xenXMConfigSetString(conf, "kernel", def->os.kernel) < 0) + xenConfigSetString(conf, "kernel", def->os.kernel) < 0) return -1; if (def->os.initrd && - xenXMConfigSetString(conf, "ramdisk", def->os.initrd) < 0) + xenConfigSetString(conf, "ramdisk", def->os.initrd) < 0) return -1; if (def->os.cmdline && - xenXMConfigSetString(conf, "extra", def->os.cmdline) < 0) + xenConfigSetString(conf, "extra", def->os.cmdline) < 0) return -1; } /* !hvm */ @@ -1807,52 +1807,52 @@ xenFormatVfb(virConfPtr conf, virDomainDefPtr def, int xendConfigVersion) if (def->ngraphics == 1) { if (hvm || (xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) { if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { - if (xenXMConfigSetInt(conf, "sdl", 1) < 0) + if (xenConfigSetInt(conf, "sdl", 1) < 0) return -1; - if (xenXMConfigSetInt(conf, "vnc", 0) < 0) + if (xenConfigSetInt(conf, "vnc", 0) < 0) return -1; if (def->graphics[0]->data.sdl.display && - xenXMConfigSetString(conf, "display", - def->graphics[0]->data.sdl.display) < 0) + xenConfigSetString(conf, "display", + def->graphics[0]->data.sdl.display) < 0) return -1; if (def->graphics[0]->data.sdl.xauth && - xenXMConfigSetString(conf, "xauthority", - def->graphics[0]->data.sdl.xauth) < 0) + xenConfigSetString(conf, "xauthority", + def->graphics[0]->data.sdl.xauth) < 0) return -1; } else { const char *listenAddr; - if (xenXMConfigSetInt(conf, "sdl", 0) < 0) + if (xenConfigSetInt(conf, "sdl", 0) < 0) return -1; - if (xenXMConfigSetInt(conf, "vnc", 1) < 0) + if (xenConfigSetInt(conf, "vnc", 1) < 0) return -1; - if (xenXMConfigSetInt(conf, "vncunused", + if (xenConfigSetInt(conf, "vncunused", def->graphics[0]->data.vnc.autoport ? 1 : 0) < 0) return -1; if (!def->graphics[0]->data.vnc.autoport && - xenXMConfigSetInt(conf, "vncdisplay", - def->graphics[0]->data.vnc.port - 5900) < 0) + xenConfigSetInt(conf, "vncdisplay", + def->graphics[0]->data.vnc.port - 5900) < 0) return -1; listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0); if (listenAddr && - xenXMConfigSetString(conf, "vnclisten", listenAddr) < 0) + xenConfigSetString(conf, "vnclisten", listenAddr) < 0) return -1; if (def->graphics[0]->data.vnc.auth.passwd && - xenXMConfigSetString(conf, "vncpasswd", - def->graphics[0]->data.vnc.auth.passwd) < 0) + xenConfigSetString(conf, "vncpasswd", + def->graphics[0]->data.vnc.auth.passwd) < 0) return -1; if (def->graphics[0]->data.vnc.keymap && - xenXMConfigSetString(conf, "keymap", - def->graphics[0]->data.vnc.keymap) < 0) + xenConfigSetString(conf, "keymap", + def->graphics[0]->data.vnc.keymap) < 0) return -1; } } else { @@ -1928,7 +1928,7 @@ xenFormatSound(virConfPtr conf, virDomainDefPtr def) str = virBufferContentAndReset(&buf); if (ret == 0) - ret = xenXMConfigSetString(conf, "soundhw", str); + ret = xenConfigSetString(conf, "soundhw", str); VIR_FREE(str); if (ret < 0) @@ -1948,22 +1948,22 @@ xenFormatInputDevs(virConfPtr conf, virDomainDefPtr def) if (STREQ(def->os.type, "hvm")) { for (i = 0; i < def->ninputs; i++) { if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) { - if (xenXMConfigSetInt(conf, "usb", 1) < 0) + if (xenConfigSetInt(conf, "usb", 1) < 0) return -1; switch (def->inputs[i]->type) { case VIR_DOMAIN_INPUT_TYPE_MOUSE: - if (xenXMConfigSetString(conf, "usbdevice", "mouse") < 0) + if (xenConfigSetString(conf, "usbdevice", "mouse") < 0) return -1; break; case VIR_DOMAIN_INPUT_TYPE_TABLET: - if (xenXMConfigSetString(conf, "usbdevice", "tablet") < 0) + if (xenConfigSetString(conf, "usbdevice", "tablet") < 0) return -1; break; case VIR_DOMAIN_INPUT_TYPE_KBD: - if (xenXMConfigSetString(conf, "usbdevice", "keyboard") < 0) + if (xenConfigSetString(conf, "usbdevice", "keyboard") < 0) return -1; break; diff --git a/src/xenconfig/xen_common.h b/src/xenconfig/xen_common.h index 9f50aef..e993b21 100644 --- a/src/xenconfig/xen_common.h +++ b/src/xenconfig/xen_common.h @@ -27,11 +27,25 @@ # include "virconf.h" # include "domain_conf.h" -int -xenConfigGetString(virConfPtr conf, - const char *name, - const char **value, - const char *def); +int xenConfigGetString(virConfPtr conf, + const char *name, + const char **value, + const char *def); + +int xenConfigGetBool(virConfPtr conf, const char *name, int *value, int def); + +int xenConfigSetInt(virConfPtr conf, const char *name, long long value); + +int xenConfigSetString(virConfPtr conf, const char *setting, const char *value); + +int xenConfigGetULong(virConfPtr conf, + const char *name, + unsigned long *value, + unsigned long def); + +int xenConfigCopyStringOpt(virConfPtr conf, + const char *name, + char **value); int xenParseConfigCommon(virConfPtr conf, virDomainDefPtr def, -- 1.8.4.5

Introduce a xen xl parser This parser allows for users to convert the new xl disk format and spice graphics config to libvirt xml format and vice versa.Regarding the spice graphics config, the code is pretty much straight forward For the disk {formating, parsing} this parser takes care of the new xl format which include positional parameters and key/value parameters In xl format disk config a <diskspec> consists of parameters separated by commas.If the parameters do not contain an '=' they are automatically assigned to certain options following the order below target, format, vdev, access The above are the only mandatory parameters in the <diskspec> but there are many more disk config options.This options can be specified as key=value pairs This takes care of the rest of the options such as devtype, backend, backendtype, script, direct-io-safe, The positional paramters can also be specified in key/value form for example /dev/vg/guest-volume,,hda /dev/vg/guest-volume,raw,hda,rw format=raw, vdev=hda, access=rw, target=/dev/vg/guest-volume are interpleted to one config In xm format a config equivalent to the one about would have been raw:/dev/vg/guest-volume,hda,w As of this commit, libvirt can not convert xl disk config such as /dev/vg/guest-volume,,hda to libvirt xml <disk type='block' device='disk'> <driver name='qemu' type='raw'/> <source file=/dev/vg/guest-volume/> <target dev='hdc' bus='ide'/> </disk> Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> --- configure.ac | 7 + src/Makefile.am | 21 +- src/libvirt_xenconfig.syms | 4 + src/xenconfig/libxlu_disk_i.h | 28 +++ src/xenconfig/libxlu_disk_l.l | 259 +++++++++++++++++++++++ src/xenconfig/xen_common.c | 3 +- src/xenconfig/xen_xl.c | 479 ++++++++++++++++++++++++++++++++++++++++++ src/xenconfig/xen_xl.h | 29 +++ 8 files changed, 825 insertions(+), 5 deletions(-) create mode 100644 src/xenconfig/libxlu_disk_i.h create mode 100644 src/xenconfig/libxlu_disk_l.l create mode 100644 src/xenconfig/xen_xl.c create mode 100644 src/xenconfig/xen_xl.h diff --git a/configure.ac b/configure.ac index f93c6c2..0daf411 100644 --- a/configure.ac +++ b/configure.ac @@ -2177,6 +2177,13 @@ if test -z "$PERL"; then AC_MSG_ERROR([Failed to find perl.]) fi +AC_PROG_LEX +if test "x$LEX" != xflex; then + LEX="$SHELL $missing_dir/missing flex" + AC_SUBST([LEX_OUPTUT_ROOT], [lex.yy]) + AC_SUBST([LEXLIB], ['']) +fi + AC_ARG_WITH([test-suite], [AS_HELP_STRING([--with-test-suite], [build test suite by default @<:@default=check@:>@])], diff --git a/src/Makefile.am b/src/Makefile.am index 46e411e..52c7f1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,7 +35,6 @@ INCLUDES = -I../gnulib/lib \ $(GETTEXT_CPPFLAGS) AM_CFLAGS = $(LIBXML_CFLAGS) \ - $(WARN_CFLAGS) \ $(LOCK_CHECKING_CFLAGS) \ $(WIN32_EXTRA_CFLAGS) \ $(COVERAGE_CFLAGS) @@ -964,11 +963,25 @@ CPU_SOURCES = \ VMX_SOURCES = \ vmx/vmx.c vmx/vmx.h +XENCONFIG_GENERATED = \ + xenconfig/libxlu_disk_l.c \ + xenconfig/libxlu_disk_l.h + +$(XENCONFIG_GENERATED): $(srcdir)/xenconfig/libxlu_disk_l.l \ + $(srcdir)/xenconfig/libxlu_disk_i.h Makefile.am + $(AM_V_GEN)$(LEX) --outfile=$(srcdir)/xenconfig/libxlu_disk_l.c \ + --header-file=$(srcdir)/xenconfig/libxlu_disk_l.h \ + $(srcdir)/xenconfig/libxlu_disk_l.l + +CLEANFILES += $(XENCONFIG_GENERATED) + XENCONFIG_SOURCES = \ xenconfig/xenxs_private.h \ - xenconfig/xen_common.c xenconfig/xen_common.h \ - xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ - xenconfig/xen_xm.c xenconfig/xen_xm.h + xenconfig/xen_common.c xenconfig/xen_common.h \ + xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ + xenconfig/xen_xm.c xenconfig/xen_xm.h \ + xenconfig/xen_xl.c xenconfig/xen_xl.h \ + $(XENCONFIG_GENERATED) pkgdata_DATA = cpu/cpu_map.xml diff --git a/src/libvirt_xenconfig.syms b/src/libvirt_xenconfig.syms index 6541685..3e2e5d6 100644 --- a/src/libvirt_xenconfig.syms +++ b/src/libvirt_xenconfig.syms @@ -16,6 +16,10 @@ xenParseSxprChar; xenParseSxprSound; xenParseSxprString; +#xenconfig/xen_xl.h +xenFormatXL; +xenParseXL; + # xenconfig/xen_xm.h xenFormatXM; xenParseXM; diff --git a/src/xenconfig/libxlu_disk_i.h b/src/xenconfig/libxlu_disk_i.h new file mode 100644 index 0000000..911ea42 --- /dev/null +++ b/src/xenconfig/libxlu_disk_i.h @@ -0,0 +1,28 @@ +#ifndef LIBXLU_DISK_I_H +#define LIBXLU_DISK_I_H + +#include "../util/virconf.h" + +typedef struct { + virConfPtr conf; + int err; + void *scanner; + YY_BUFFER_STATE buf; + virDomainDiskDefPtr disk; + int access_set, had_depr_prefix; + const char *spec; +} DiskParseContext; + +void xlu__disk_err(DiskParseContext *dpc, const char *erroneous, + const char *message); + + +#endif /*LIBXLU_DISK_I_H*/ + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/xenconfig/libxlu_disk_l.l b/src/xenconfig/libxlu_disk_l.l new file mode 100644 index 0000000..8842318 --- /dev/null +++ b/src/xenconfig/libxlu_disk_l.l @@ -0,0 +1,259 @@ +/* -*- fundamental -*- */ +/* + * libxlu_disk_l.l - parser for disk specification strings + * + * Copyright (C) 2011 Citrix Ltd. + * Author Ian Jackson <ian.jackson@eu.citrix.com> + * + * This program 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; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program 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. + */ + +/* + * Parsing the old xm/xend/xl-4.1 disk specs is a tricky problem, + * because the target string might in theory contain "," which is the + * delimiter we use for stripping off things on the RHS, and ":", + * which is the delimiter we use for stripping off things on the LHS. + * + * In this parser we do not support such target strings in the old + * syntax; if the target string has to contain "," or ":" the new + * syntax's "target=" should be used. + */ +%{ +# include <config.h> +# include <stdio.h> +# include "virstring.h" +# include "virstoragefile.h" +# include "viralloc.h" +# include "virconf.h" +# include "domain_conf.h" +# include "viralloc.h" +# include "virstring.h" +# include "xen_xl.h" +# include "libxlu_disk_i.h" +# include "libxlu_disk_i.h" + +#define YY_NO_INPUT +#define VIR_FROM_THIS VIR_FROM_NONE + +/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes + * it to fail to declare these functions, which it defines. So declare + * them ourselves. Hopefully we won't have to simultaneously support + * a flex version which declares these differently somehow. */ +int xlu__disk_yyget_column(yyscan_t yyscanner); +void xlu__disk_yyset_column(int column_no, yyscan_t yyscanner); + + +/*----- useful macros and functions used in actions ----- + * we use macros in the actual rules to keep the actions short + * and particularly to avoid repeating boilerplate values such as + * DPC->disk, yytext, etc. */ + +/* For actions whose patterns contain '=', finds the start of the value */ +#define FROMEQUALS (strchr(yytext,'=')+1) + +/* Chops the delimiter off, modifying yytext and yyleng. */ +#define STRIP(delim) do{ \ + if (yyleng>0 && yytext[yyleng-1]==(delim)) \ + yytext[--yyleng] = 0; \ + }while(0) + +/* Sets a string value, checking it hasn't been set already. */ +#define SAVESTRING(what,loc,val) do{ \ + savestring(DPC, what " respecified", &DPC->disk->loc, (val)); \ + }while(0) + + +static void +savestring(DiskParseContext *dpc, + const char *what_respecified, + char **update, + const char *value) +{ + if (*update) { + if (**update) { + xlu__disk_err(dpc, value, what_respecified); + return; + } + + free(*update); /* do not complain about overwriting empty strings */ + } + + *update = strdup(value); +} + +#define DPC dpc /* our convention in lexer helper functions */ + +/* Sets ->readwrite from the string. This ought to be an enum, perhaps. */ +static void +setaccess(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "r") || STREQ(str, "ro")) { + dpc->disk->src->readonly = 1; + } else if (STREQ(str, "w!") || STREQ(str, "!")) { + dpc->disk->src->shared = 1; + } else { + xlu__disk_err(dpc,str,"unknown value for access"); + } +} + +/* Sets ->format from the string. IDL should provide something for this. */ +static void +setformat(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW); + else if (STREQ(str, "raw")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW); + else if (STREQ(str, "qcow")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW); + else if (STREQ(str, "qcow2")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW2); + else if (STREQ(str, "vhd")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_VHD); + else xlu__disk_err(dpc, str, "unknown value for format"); +} + + +/* Sets ->backend from the string. IDL should provide something for this. */ +static void +setdrivertype(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "phy")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "phy")); + else if (STREQ(str, "tap")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "tap")); + else if (STREQ(str, "qdisk")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "qemu")); + else if (STREQ(str, "")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "phy")); + else + xlu__disk_err(dpc, str, "unknown value for backendtype"); +} + + +/* Handles a vdev positional parameter which includes a devtype. */ +static int +vdev_and_devtype(DiskParseContext *dpc, char *str) +{ + /* returns 1 if it was <vdev>:<devtype>, 0 (doing nothing) otherwise */ + char *colon = strrchr(str, ':'); + if (!colon) + return 0; + + *colon++ = 0; + SAVESTRING("vdev", dst, str); + + if (STREQ(colon,"cdrom")) { + DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + } else if (STREQ(colon, "disk")) { + DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; + } else { + xlu__disk_err(DPC, colon, "unknown deprecated type"); + } + return 1; +} + +#undef DPC /* needs to be defined differently the actual lexer */ +#define DPC ((DiskParseContext*)yyextra) + +%} + +%option warn +%option nodefault +%option batch +%option 8bit +%option noyywrap +%option reentrant +%option prefix="xlu__disk_yy" +%option nounput + +%x LEXERR + +%% + + /*----- the scanner rules which do the parsing -----*/ + +[ \t\n]+/([^ \t\n].*)? { /* ignore whitespace before parameters */ } + + /* ordinary parameters setting enums or strings */ + +format=[^,]*,? { STRIP(','); setformat(DPC, FROMEQUALS); } + +cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } +devtype=cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } +devtype=disk,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; } +devtype=[^,]*,? { xlu__disk_err(DPC, yytext,"unknown value for type"); } + +access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); } +backendtype=[^,]*,? { STRIP(','); setdrivertype(DPC, FROMEQUALS); } + +vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", dst, FROMEQUALS); } + + /* the target magic parameter, eats the rest of the string */ + +target=.* { STRIP(','); SAVESTRING("target", src->path, FROMEQUALS); } + + /* unknown parameters */ + +[a-z][-a-z0-9]*=[^,],? { xlu__disk_err(DPC, yytext, "unknown parameter"); } + + /* the "/.*" in these patterns ensures that they count as if they + * matched the whole string, so these patterns take precedence */ + +(raw|qcow2?|vhd):/.* { + STRIP(':'); + DPC->had_depr_prefix=1; + setformat(DPC, yytext); + } + +tapdisk:/.* { DPC->had_depr_prefix=1; } +tap2?:/.* { DPC->had_depr_prefix=1; } +aio:/.* { DPC->had_depr_prefix=1; } +ioemu:/.* { DPC->had_depr_prefix=1; } +file:/.* { DPC->had_depr_prefix=1; } +phy:/.* { DPC->had_depr_prefix=1; } +[a-z][a-z0-9]*:/([^a-z0-9].*)? { + xlu__disk_err(DPC, yytext, "unknown deprecated disk prefix"); + return 0; + } + + /* positional parameters */ + +[^=,]*,|[^=,]+,? { + STRIP(','); + + if (DPC->err) { + /* previous errors may just lead to subsequent ones */ + } else if (!DPC->disk->src->path) { + SAVESTRING("target", src->path, yytext); + } else if (DPC->disk->src->format == VIR_STORAGE_FILE_LAST){ + setformat(DPC, yytext); + } + else if (!DPC->disk->dst) { + if (!vdev_and_devtype(DPC, yytext)) + SAVESTRING("vdev", dst, yytext); + } else if (!DPC->access_set) { + DPC->access_set = 1; + setaccess(DPC, yytext); + } else { + xlu__disk_err(DPC, yytext, "too many positional parameters"); + return 0; /* don't print any more errors */ + } +} + +. { + BEGIN(LEXERR); + yymore(); +} +<LEXERR>.* { + xlu__disk_err(DPC, yytext, "bad disk syntax"); + return 0; +} diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index d71dd07..e7545b9 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -1804,7 +1804,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..9684c4c --- /dev/null +++ b/src/xenconfig/xen_xl.c @@ -0,0 +1,479 @@ +/* + * xen_xl.c: Xen XL parsing functions + * + * 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> + */ +#include <config.h> +#include <assert.h> +#include "virconf.h" +#include "virerror.h" +#include "domain_conf.h" +#include "viralloc.h" +#include "virstring.h" +#include "xen_xl.h" +#include "libxlu_disk_l.h" +#include "libxlu_disk_i.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +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; +} + + + +void +xlu__disk_err(DiskParseContext *dpc, + const char *erroneous, + const char *message) +{ + /*virReportError(VIR_ERR_INTERNAL_ERROR, + "%s: config parsing error in disk specification: %s" + "%s%s" + " in `%s'\n", + message, + erroneous?": near `":"", erroneous?erroneous:"", erroneous?"'":"", + dpc->spec); + if (!dpc->err) + dpc->err= EINVAL; + */ +} + + +static int +dpc_prep(DiskParseContext *dpc, const char *spec) +{ + int e; + dpc->spec = spec; + + e = xlu__disk_yylex_init_extra(dpc, &dpc->scanner); + if (e) + goto fail; + + dpc->buf = xlu__disk_yy_scan_bytes(spec, strlen(spec), dpc->scanner); + if (!dpc->buf) { + e = ENOMEM; + goto fail; + } + + return 0; + + fail: + virReportError(VIR_ERR_INTERNAL_ERROR, "cannot init disk scanner: %s\n", + strerror(errno)); + return e; +} + + +static void +dpc_dispose(DiskParseContext *dpc) +{ + virDomainDiskDefFree(dpc->disk); + + if (dpc->buf) { + xlu__disk_yy_delete_buffer(dpc->buf, dpc->scanner); + dpc->buf = 0; + } + if (dpc->scanner) { + xlu__disk_yylex_destroy(dpc->scanner); + dpc->scanner = 0; + } +} + +/* + * positional parameters + * (If the <diskspec> strings are not separated by "=" + * the string is split following ',' and assigned to + * the following options in the following order) + * target,format,vdev,access + * ================================================================ + * + * The parameters below cannot be specified as positional parameters: + * + * other parameters + * devtype = <devtype> + * backendtype = <backend-type> + * parameters not taken care of + * backend = <domain-name> + * script = <script> + * direct-io-safe + * + * ================================================================ + * The parser does not take any deprecated parameters + * + * For more information refer to /xen/docs/misc/xl-disk-configuration.txt + */ +static int +xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) +{ + int e; + DiskParseContext dpc; + + virConfValuePtr list = virConfGetValue(conf, "disk"); + dpc.conf = conf; + dpc.scanner = 0; + memset(&dpc, 0, sizeof(dpc)); + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + char *specs = list->str; + dpc.spec = specs; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipdisk; + + if (!(dpc.disk = virDomainDiskDefNew())) + return -1; + dpc.disk->src->readonly = 0; + dpc.disk->src->format = VIR_STORAGE_FILE_LAST; + + e = dpc_prep(&dpc, specs); + if (e) { + dpc.err = e; + } + xlu__disk_yylex(dpc.scanner); + + if (dpc.err) { + dpc_dispose(&dpc); + } + if (dpc.disk->src->format == VIR_STORAGE_FILE_LAST) { + dpc.disk->src->format = VIR_STORAGE_FILE_RAW; + } + + if (dpc.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + dpc.disk->removable = true; + dpc.disk->src->readonly = true; + if (!dpc.disk->src->path || STREQ(dpc.disk->src->path, "")) + dpc.disk->src->format = VIR_STORAGE_FILE_NONE; + } + + if (STRPREFIX(dpc.disk->dst, "xvd") || !STREQ(def->os.type, "hvm")) { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_XEN; + } else if (STRPREFIX(dpc.disk->dst, "sd")) { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; + } else { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + } + + if (!(virDomainDiskGetDriver(dpc.disk))) + ignore_value(virDomainDiskSetDriver(dpc.disk, "phy")); + + virDomainDiskSetType(dpc.disk, STREQ(virDomainDiskGetDriver(dpc.disk), "phy") ? + VIR_STORAGE_TYPE_BLOCK : + VIR_STORAGE_TYPE_FILE); + if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, dpc.disk) < 0) + return -1; +skipdisk: + list = list->next; + virDomainDiskDefFree(dpc.disk); + dpc.disk = NULL; + } + + } + return 0; +} + + +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); + + /* 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 (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + virBufferAddLit(&buf, "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) +{ + virConfValuePtr diskVal = NULL; + size_t i = 0; + + 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) { + int ret = virConfSetValue(conf, "disk", diskVal); + diskVal = NULL; + if (ret < 0) + goto cleanup; + } + + return 0; + + cleanup: + virConfFreeValue(diskVal); + return 0; +} + + +static int +xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def) +{ + const char *listenAddr = NULL; + + if (STREQ(def->os.type, "hvm")) { /*save's CPU :-) */ + 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, "spice_mouse_agent", + 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..d60fe5e --- /dev/null +++ b/src/xenconfig/xen_xl.h @@ -0,0 +1,29 @@ +/* + * xen_xl.h: Xen XL parsing functions + * + * 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 _XEN_XL_H_ +# define _XEN_XL_H_ + +# include "xen_common.h" + +virDomainDefPtr xenParseXL(virConfPtr conn, virCapsPtr caps, + int xendConfigVersion); +virConfPtr xenFormatXL(virDomainDefPtr def, + virConnectPtr, int xendConfigVersion); +#endif /* _XEN_XL_H_ */ -- 1.8.4.5

Kiarie Kahurani wrote:
Introduce a xen xl parser
[...]
diff --git a/configure.ac b/configure.ac index f93c6c2..0daf411 100644 --- a/configure.ac +++ b/configure.ac @@ -2177,6 +2177,13 @@ if test -z "$PERL"; then AC_MSG_ERROR([Failed to find perl.]) fi
+AC_PROG_LEX +if test "x$LEX" != xflex; then + LEX="$SHELL $missing_dir/missing flex" + AC_SUBST([LEX_OUPTUT_ROOT], [lex.yy]) + AC_SUBST([LEXLIB], ['']) +fi +
As mentioned previously, I think you only need AM_PROG_FLEX here. I peeked at the macro in aclocal.m4 and it looks to handle the missing flex case.
AC_ARG_WITH([test-suite], [AS_HELP_STRING([--with-test-suite], [build test suite by default @<:@default=check@:>@])], diff --git a/src/Makefile.am b/src/Makefile.am index 46e411e..52c7f1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,7 +35,6 @@ INCLUDES = -I../gnulib/lib \ $(GETTEXT_CPPFLAGS)
AM_CFLAGS = $(LIBXML_CFLAGS) \ - $(WARN_CFLAGS) \ $(LOCK_CHECKING_CFLAGS) \ $(WIN32_EXTRA_CFLAGS) \ $(COVERAGE_CFLAGS) @@ -964,11 +963,25 @@ CPU_SOURCES = \ VMX_SOURCES = \ vmx/vmx.c vmx/vmx.h
+XENCONFIG_GENERATED = \ + xenconfig/libxlu_disk_l.c \ + xenconfig/libxlu_disk_l.h + +$(XENCONFIG_GENERATED): $(srcdir)/xenconfig/libxlu_disk_l.l \ + $(srcdir)/xenconfig/libxlu_disk_i.h Makefile.am + $(AM_V_GEN)$(LEX) --outfile=$(srcdir)/xenconfig/libxlu_disk_l.c \ + --header-file=$(srcdir)/xenconfig/libxlu_disk_l.h \ + $(srcdir)/xenconfig/libxlu_disk_l.l + +CLEANFILES += $(XENCONFIG_GENERATED) + XENCONFIG_SOURCES = \ xenconfig/xenxs_private.h \ - xenconfig/xen_common.c xenconfig/xen_common.h \ - xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ - xenconfig/xen_xm.c xenconfig/xen_xm.h + xenconfig/xen_common.c xenconfig/xen_common.h \ + xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ + xenconfig/xen_xm.c xenconfig/xen_xm.h \ + xenconfig/xen_xl.c xenconfig/xen_xl.h \
+ $(XENCONFIG_GENERATED)
Same comment as before. According to the automake documentation this should be done with BUILT_SOURCES += xenconfig/libxlu_disk_l.h xenconfig/libxlu_disk_l.c XENCONFIG_SOURCES = \ xenconfig/xenxs_private.h \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h \ xenconfig/xen_xl.c xenconfig/xen_xl.h \ xenconfig/libxlu_disk_l.l But also as mentioned before, I can't figure out how to convince automake to tell flex to generate the header file as well as the .c file. Eric, do you have any experience with automake and flex? The following thread makes it sound as though automake supports flex's '--header-file=' option, but I can't find any hint on how to make it work http://lists.gnu.org/archive/html/bug-automake/2012-08/msg00069.html Regards, Jim
pkgdata_DATA = cpu/cpu_map.xml
diff --git a/src/libvirt_xenconfig.syms b/src/libvirt_xenconfig.syms index 6541685..3e2e5d6 100644 --- a/src/libvirt_xenconfig.syms +++ b/src/libvirt_xenconfig.syms @@ -16,6 +16,10 @@ xenParseSxprChar; xenParseSxprSound; xenParseSxprString;
+#xenconfig/xen_xl.h +xenFormatXL; +xenParseXL; + # xenconfig/xen_xm.h xenFormatXM; xenParseXM; diff --git a/src/xenconfig/libxlu_disk_i.h b/src/xenconfig/libxlu_disk_i.h new file mode 100644 index 0000000..911ea42 --- /dev/null +++ b/src/xenconfig/libxlu_disk_i.h @@ -0,0 +1,28 @@ +#ifndef LIBXLU_DISK_I_H +#define LIBXLU_DISK_I_H + +#include "../util/virconf.h" + +typedef struct { + virConfPtr conf; + int err; + void *scanner; + YY_BUFFER_STATE buf; + virDomainDiskDefPtr disk; + int access_set, had_depr_prefix; + const char *spec; +} DiskParseContext; + +void xlu__disk_err(DiskParseContext *dpc, const char *erroneous, + const char *message); + + +#endif /*LIBXLU_DISK_I_H*/ + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/xenconfig/libxlu_disk_l.l b/src/xenconfig/libxlu_disk_l.l new file mode 100644 index 0000000..8842318 --- /dev/null +++ b/src/xenconfig/libxlu_disk_l.l @@ -0,0 +1,259 @@ +/* -*- fundamental -*- */ +/* + * libxlu_disk_l.l - parser for disk specification strings + * + * Copyright (C) 2011 Citrix Ltd. + * Author Ian Jackson <ian.jackson@eu.citrix.com> + * + * This program 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; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program 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. + */ + +/* + * Parsing the old xm/xend/xl-4.1 disk specs is a tricky problem, + * because the target string might in theory contain "," which is the + * delimiter we use for stripping off things on the RHS, and ":", + * which is the delimiter we use for stripping off things on the LHS. + * + * In this parser we do not support such target strings in the old + * syntax; if the target string has to contain "," or ":" the new + * syntax's "target=" should be used. + */ +%{ +# include <config.h> +# include <stdio.h> +# include "virstring.h" +# include "virstoragefile.h" +# include "viralloc.h" +# include "virconf.h" +# include "domain_conf.h" +# include "viralloc.h" +# include "virstring.h" +# include "xen_xl.h" +# include "libxlu_disk_i.h" +# include "libxlu_disk_i.h" + +#define YY_NO_INPUT +#define VIR_FROM_THIS VIR_FROM_NONE + +/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes + * it to fail to declare these functions, which it defines. So declare + * them ourselves. Hopefully we won't have to simultaneously support + * a flex version which declares these differently somehow. */ +int xlu__disk_yyget_column(yyscan_t yyscanner); +void xlu__disk_yyset_column(int column_no, yyscan_t yyscanner); + + +/*----- useful macros and functions used in actions ----- + * we use macros in the actual rules to keep the actions short + * and particularly to avoid repeating boilerplate values such as + * DPC->disk, yytext, etc. */ + +/* For actions whose patterns contain '=', finds the start of the value */ +#define FROMEQUALS (strchr(yytext,'=')+1) + +/* Chops the delimiter off, modifying yytext and yyleng. */ +#define STRIP(delim) do{ \ + if (yyleng>0 && yytext[yyleng-1]==(delim)) \ + yytext[--yyleng] = 0; \ + }while(0) + +/* Sets a string value, checking it hasn't been set already. */ +#define SAVESTRING(what,loc,val) do{ \ + savestring(DPC, what " respecified", &DPC->disk->loc, (val)); \ + }while(0) + + +static void +savestring(DiskParseContext *dpc, + const char *what_respecified, + char **update, + const char *value) +{ + if (*update) { + if (**update) { + xlu__disk_err(dpc, value, what_respecified); + return; + } + + free(*update); /* do not complain about overwriting empty strings */ + } + + *update = strdup(value); +} + +#define DPC dpc /* our convention in lexer helper functions */ + +/* Sets ->readwrite from the string. This ought to be an enum, perhaps. */ +static void +setaccess(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "r") || STREQ(str, "ro")) { + dpc->disk->src->readonly = 1; + } else if (STREQ(str, "w!") || STREQ(str, "!")) { + dpc->disk->src->shared = 1; + } else { + xlu__disk_err(dpc,str,"unknown value for access"); + } +} + +/* Sets ->format from the string. IDL should provide something for this. */ +static void +setformat(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW); + else if (STREQ(str, "raw")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW); + else if (STREQ(str, "qcow")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW); + else if (STREQ(str, "qcow2")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW2); + else if (STREQ(str, "vhd")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_VHD); + else xlu__disk_err(dpc, str, "unknown value for format"); +} + + +/* Sets ->backend from the string. IDL should provide something for this. */ +static void +setdrivertype(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "phy")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "phy")); + else if (STREQ(str, "tap")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "tap")); + else if (STREQ(str, "qdisk")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "qemu")); + else if (STREQ(str, "")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "phy")); + else + xlu__disk_err(dpc, str, "unknown value for backendtype"); +} + + +/* Handles a vdev positional parameter which includes a devtype. */ +static int +vdev_and_devtype(DiskParseContext *dpc, char *str) +{ + /* returns 1 if it was <vdev>:<devtype>, 0 (doing nothing) otherwise */ + char *colon = strrchr(str, ':'); + if (!colon) + return 0; + + *colon++ = 0; + SAVESTRING("vdev", dst, str); + + if (STREQ(colon,"cdrom")) { + DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + } else if (STREQ(colon, "disk")) { + DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; + } else { + xlu__disk_err(DPC, colon, "unknown deprecated type"); + } + return 1; +} + +#undef DPC /* needs to be defined differently the actual lexer */ +#define DPC ((DiskParseContext*)yyextra) + +%} + +%option warn +%option nodefault +%option batch +%option 8bit +%option noyywrap +%option reentrant +%option prefix="xlu__disk_yy" +%option nounput + +%x LEXERR + +%% + + /*----- the scanner rules which do the parsing -----*/ + +[ \t\n]+/([^ \t\n].*)? { /* ignore whitespace before parameters */ } + + /* ordinary parameters setting enums or strings */ + +format=[^,]*,? { STRIP(','); setformat(DPC, FROMEQUALS); } + +cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } +devtype=cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } +devtype=disk,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; } +devtype=[^,]*,? { xlu__disk_err(DPC, yytext,"unknown value for type"); } + +access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); } +backendtype=[^,]*,? { STRIP(','); setdrivertype(DPC, FROMEQUALS); } + +vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", dst, FROMEQUALS); } + + /* the target magic parameter, eats the rest of the string */ + +target=.* { STRIP(','); SAVESTRING("target", src->path, FROMEQUALS); } + + /* unknown parameters */ + +[a-z][-a-z0-9]*=[^,],? { xlu__disk_err(DPC, yytext, "unknown parameter"); } + + /* the "/.*" in these patterns ensures that they count as if they + * matched the whole string, so these patterns take precedence */ + +(raw|qcow2?|vhd):/.* { + STRIP(':'); + DPC->had_depr_prefix=1; + setformat(DPC, yytext); + } + +tapdisk:/.* { DPC->had_depr_prefix=1; } +tap2?:/.* { DPC->had_depr_prefix=1; } +aio:/.* { DPC->had_depr_prefix=1; } +ioemu:/.* { DPC->had_depr_prefix=1; } +file:/.* { DPC->had_depr_prefix=1; } +phy:/.* { DPC->had_depr_prefix=1; } +[a-z][a-z0-9]*:/([^a-z0-9].*)? { + xlu__disk_err(DPC, yytext, "unknown deprecated disk prefix"); + return 0; + } + + /* positional parameters */ + +[^=,]*,|[^=,]+,? { + STRIP(','); + + if (DPC->err) { + /* previous errors may just lead to subsequent ones */ + } else if (!DPC->disk->src->path) { + SAVESTRING("target", src->path, yytext); + } else if (DPC->disk->src->format == VIR_STORAGE_FILE_LAST){ + setformat(DPC, yytext); + } + else if (!DPC->disk->dst) { + if (!vdev_and_devtype(DPC, yytext)) + SAVESTRING("vdev", dst, yytext); + } else if (!DPC->access_set) { + DPC->access_set = 1; + setaccess(DPC, yytext); + } else { + xlu__disk_err(DPC, yytext, "too many positional parameters"); + return 0; /* don't print any more errors */ + } +} + +. { + BEGIN(LEXERR); + yymore(); +} +<LEXERR>.* { + xlu__disk_err(DPC, yytext, "bad disk syntax"); + return 0; +} diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index d71dd07..e7545b9 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -1804,7 +1804,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..9684c4c --- /dev/null +++ b/src/xenconfig/xen_xl.c @@ -0,0 +1,479 @@ +/* + * xen_xl.c: Xen XL parsing functions + * + * 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> + */ +#include <config.h> +#include <assert.h> +#include "virconf.h" +#include "virerror.h" +#include "domain_conf.h" +#include "viralloc.h" +#include "virstring.h" +#include "xen_xl.h" +#include "libxlu_disk_l.h" +#include "libxlu_disk_i.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +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; +} + + + +void +xlu__disk_err(DiskParseContext *dpc, + const char *erroneous, + const char *message) +{ + /*virReportError(VIR_ERR_INTERNAL_ERROR, + "%s: config parsing error in disk specification: %s" + "%s%s" + " in `%s'\n", + message, + erroneous?": near `":"", erroneous?erroneous:"", erroneous?"'":"", + dpc->spec); + if (!dpc->err) + dpc->err= EINVAL; + */ +} + + +static int +dpc_prep(DiskParseContext *dpc, const char *spec) +{ + int e; + dpc->spec = spec; + + e = xlu__disk_yylex_init_extra(dpc, &dpc->scanner); + if (e) + goto fail; + + dpc->buf = xlu__disk_yy_scan_bytes(spec, strlen(spec), dpc->scanner); + if (!dpc->buf) { + e = ENOMEM; + goto fail; + } + + return 0; + + fail: + virReportError(VIR_ERR_INTERNAL_ERROR, "cannot init disk scanner: %s\n", + strerror(errno)); + return e; +} + + +static void +dpc_dispose(DiskParseContext *dpc) +{ + virDomainDiskDefFree(dpc->disk); + + if (dpc->buf) { + xlu__disk_yy_delete_buffer(dpc->buf, dpc->scanner); + dpc->buf = 0; + } + if (dpc->scanner) { + xlu__disk_yylex_destroy(dpc->scanner); + dpc->scanner = 0; + } +} + +/* + * positional parameters + * (If the <diskspec> strings are not separated by "=" + * the string is split following ',' and assigned to + * the following options in the following order) + * target,format,vdev,access + * ================================================================ + * + * The parameters below cannot be specified as positional parameters: + * + * other parameters + * devtype = <devtype> + * backendtype = <backend-type> + * parameters not taken care of + * backend = <domain-name> + * script = <script> + * direct-io-safe + * + * ================================================================ + * The parser does not take any deprecated parameters + * + * For more information refer to /xen/docs/misc/xl-disk-configuration.txt + */ +static int +xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) +{ + int e; + DiskParseContext dpc; + + virConfValuePtr list = virConfGetValue(conf, "disk"); + dpc.conf = conf; + dpc.scanner = 0; + memset(&dpc, 0, sizeof(dpc)); + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + char *specs = list->str; + dpc.spec = specs; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipdisk; + + if (!(dpc.disk = virDomainDiskDefNew())) + return -1; + dpc.disk->src->readonly = 0; + dpc.disk->src->format = VIR_STORAGE_FILE_LAST; + + e = dpc_prep(&dpc, specs); + if (e) { + dpc.err = e; + } + xlu__disk_yylex(dpc.scanner); + + if (dpc.err) { + dpc_dispose(&dpc); + } + if (dpc.disk->src->format == VIR_STORAGE_FILE_LAST) { + dpc.disk->src->format = VIR_STORAGE_FILE_RAW; + } + + if (dpc.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + dpc.disk->removable = true; + dpc.disk->src->readonly = true; + if (!dpc.disk->src->path || STREQ(dpc.disk->src->path, "")) + dpc.disk->src->format = VIR_STORAGE_FILE_NONE; + } + + if (STRPREFIX(dpc.disk->dst, "xvd") || !STREQ(def->os.type, "hvm")) { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_XEN; + } else if (STRPREFIX(dpc.disk->dst, "sd")) { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; + } else { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + } + + if (!(virDomainDiskGetDriver(dpc.disk))) + ignore_value(virDomainDiskSetDriver(dpc.disk, "phy")); + + virDomainDiskSetType(dpc.disk, STREQ(virDomainDiskGetDriver(dpc.disk), "phy") ? + VIR_STORAGE_TYPE_BLOCK : + VIR_STORAGE_TYPE_FILE); + if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, dpc.disk) < 0) + return -1; +skipdisk: + list = list->next; + virDomainDiskDefFree(dpc.disk); + dpc.disk = NULL; + } + + } + return 0; +} + + +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); + + /* 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 (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + virBufferAddLit(&buf, "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) +{ + virConfValuePtr diskVal = NULL; + size_t i = 0; + + 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) { + int ret = virConfSetValue(conf, "disk", diskVal); + diskVal = NULL; + if (ret < 0) + goto cleanup; + } + + return 0; + + cleanup: + virConfFreeValue(diskVal); + return 0; +} + + +static int +xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def) +{ + const char *listenAddr = NULL; + + if (STREQ(def->os.type, "hvm")) { /*save's CPU :-) */ + 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, "spice_mouse_agent", + 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..d60fe5e --- /dev/null +++ b/src/xenconfig/xen_xl.h @@ -0,0 +1,29 @@ +/* + * xen_xl.h: Xen XL parsing functions + * + * 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 _XEN_XL_H_ +# define _XEN_XL_H_ + +# include "xen_common.h" + +virDomainDefPtr xenParseXL(virConfPtr conn, virCapsPtr caps, + int xendConfigVersion); +virConfPtr xenFormatXL(virDomainDefPtr def, + virConnectPtr, int xendConfigVersion); +#endif /* _XEN_XL_H_ */

On Thu, Sep 11, 2014 at 06:14:12PM -0600, Jim Fehlig wrote:
Kiarie Kahurani wrote:
Introduce a xen xl parser
[...]
diff --git a/configure.ac b/configure.ac index f93c6c2..0daf411 100644 --- a/configure.ac +++ b/configure.ac @@ -2177,6 +2177,13 @@ if test -z "$PERL"; then AC_MSG_ERROR([Failed to find perl.]) fi
+AC_PROG_LEX +if test "x$LEX" != xflex; then + LEX="$SHELL $missing_dir/missing flex" + AC_SUBST([LEX_OUPTUT_ROOT], [lex.yy]) + AC_SUBST([LEXLIB], ['']) +fi +
As mentioned previously, I think you only need AM_PROG_FLEX here. I peeked at the macro in aclocal.m4 and it looks to handle the missing flex case.
AC_ARG_WITH([test-suite], [AS_HELP_STRING([--with-test-suite], [build test suite by default @<:@default=check@:>@])], diff --git a/src/Makefile.am b/src/Makefile.am index 46e411e..52c7f1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,7 +35,6 @@ INCLUDES = -I../gnulib/lib \ $(GETTEXT_CPPFLAGS)
AM_CFLAGS = $(LIBXML_CFLAGS) \ - $(WARN_CFLAGS) \ $(LOCK_CHECKING_CFLAGS) \ $(WIN32_EXTRA_CFLAGS) \ $(COVERAGE_CFLAGS) @@ -964,11 +963,25 @@ CPU_SOURCES = \ VMX_SOURCES = \ vmx/vmx.c vmx/vmx.h
+XENCONFIG_GENERATED = \ + xenconfig/libxlu_disk_l.c \ + xenconfig/libxlu_disk_l.h + +$(XENCONFIG_GENERATED): $(srcdir)/xenconfig/libxlu_disk_l.l \ + $(srcdir)/xenconfig/libxlu_disk_i.h Makefile.am + $(AM_V_GEN)$(LEX) --outfile=$(srcdir)/xenconfig/libxlu_disk_l.c \ + --header-file=$(srcdir)/xenconfig/libxlu_disk_l.h \ + $(srcdir)/xenconfig/libxlu_disk_l.l + +CLEANFILES += $(XENCONFIG_GENERATED) + XENCONFIG_SOURCES = \ xenconfig/xenxs_private.h \ - xenconfig/xen_common.c xenconfig/xen_common.h \ - xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ - xenconfig/xen_xm.c xenconfig/xen_xm.h + xenconfig/xen_common.c xenconfig/xen_common.h \ + xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ + xenconfig/xen_xm.c xenconfig/xen_xm.h \ + xenconfig/xen_xl.c xenconfig/xen_xl.h \
+ $(XENCONFIG_GENERATED)
Same comment as before. According to the automake documentation this should be done with
BUILT_SOURCES += xenconfig/libxlu_disk_l.h xenconfig/libxlu_disk_l.c
XENCONFIG_SOURCES = \ xenconfig/xenxs_private.h \ xenconfig/xen_common.c xenconfig/xen_common.h \ xenconfig/xen_sxpr.c xenconfig/xen_sxpr.h \ xenconfig/xen_xm.c xenconfig/xen_xm.h \ xenconfig/xen_xl.c xenconfig/xen_xl.h \ xenconfig/libxlu_disk_l.l
But also as mentioned before, I can't figure out how to convince automake to tell flex to generate the header file as well as the .c file.
Eric, do you have any experience with automake and flex? The following thread makes it sound as though automake supports flex's '--header-file=' option, but I can't find any hint on how to make it work
http://lists.gnu.org/archive/html/bug-automake/2012-08/msg00069.html
Am not sure this approach is going to work. I have two problems here The flex generated file has used parameters so the flags used to compile it should be different from those used to compile the other files With your approach flex will generate a file named lex.xlu_disk_yy.la which apparently does not form a valid library name(below) I want to compile xenconfig sources separately from the flex generated file(so as to handle the separate flags). With separate flags I am getting rid of all the warnings when compiling the flex file since they are mostly useless as its almost impossible to edit the file manually with every compile. I want to follow my earlier approach so as to force flex to generate a file with a suitable name(then generate a suitable .la file from it)
Regards, Jim
pkgdata_DATA = cpu/cpu_map.xml
diff --git a/src/libvirt_xenconfig.syms b/src/libvirt_xenconfig.syms index 6541685..3e2e5d6 100644 --- a/src/libvirt_xenconfig.syms +++ b/src/libvirt_xenconfig.syms @@ -16,6 +16,10 @@ xenParseSxprChar; xenParseSxprSound; xenParseSxprString;
+#xenconfig/xen_xl.h +xenFormatXL; +xenParseXL; + # xenconfig/xen_xm.h xenFormatXM; xenParseXM; diff --git a/src/xenconfig/libxlu_disk_i.h b/src/xenconfig/libxlu_disk_i.h new file mode 100644 index 0000000..911ea42 --- /dev/null +++ b/src/xenconfig/libxlu_disk_i.h @@ -0,0 +1,28 @@ +#ifndef LIBXLU_DISK_I_H +#define LIBXLU_DISK_I_H + +#include "../util/virconf.h" + +typedef struct { + virConfPtr conf; + int err; + void *scanner; + YY_BUFFER_STATE buf; + virDomainDiskDefPtr disk; + int access_set, had_depr_prefix; + const char *spec; +} DiskParseContext; + +void xlu__disk_err(DiskParseContext *dpc, const char *erroneous, + const char *message); + + +#endif /*LIBXLU_DISK_I_H*/ + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/xenconfig/libxlu_disk_l.l b/src/xenconfig/libxlu_disk_l.l new file mode 100644 index 0000000..8842318 --- /dev/null +++ b/src/xenconfig/libxlu_disk_l.l @@ -0,0 +1,259 @@ +/* -*- fundamental -*- */ +/* + * libxlu_disk_l.l - parser for disk specification strings + * + * Copyright (C) 2011 Citrix Ltd. + * Author Ian Jackson <ian.jackson@eu.citrix.com> + * + * This program 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; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program 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. + */ + +/* + * Parsing the old xm/xend/xl-4.1 disk specs is a tricky problem, + * because the target string might in theory contain "," which is the + * delimiter we use for stripping off things on the RHS, and ":", + * which is the delimiter we use for stripping off things on the LHS. + * + * In this parser we do not support such target strings in the old + * syntax; if the target string has to contain "," or ":" the new + * syntax's "target=" should be used. + */ +%{ +# include <config.h> +# include <stdio.h> +# include "virstring.h" +# include "virstoragefile.h" +# include "viralloc.h" +# include "virconf.h" +# include "domain_conf.h" +# include "viralloc.h" +# include "virstring.h" +# include "xen_xl.h" +# include "libxlu_disk_i.h" +# include "libxlu_disk_i.h" + +#define YY_NO_INPUT +#define VIR_FROM_THIS VIR_FROM_NONE + +/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes + * it to fail to declare these functions, which it defines. So declare + * them ourselves. Hopefully we won't have to simultaneously support + * a flex version which declares these differently somehow. */ +int xlu__disk_yyget_column(yyscan_t yyscanner); +void xlu__disk_yyset_column(int column_no, yyscan_t yyscanner); + + +/*----- useful macros and functions used in actions ----- + * we use macros in the actual rules to keep the actions short + * and particularly to avoid repeating boilerplate values such as + * DPC->disk, yytext, etc. */ + +/* For actions whose patterns contain '=', finds the start of the value */ +#define FROMEQUALS (strchr(yytext,'=')+1) + +/* Chops the delimiter off, modifying yytext and yyleng. */ +#define STRIP(delim) do{ \ + if (yyleng>0 && yytext[yyleng-1]==(delim)) \ + yytext[--yyleng] = 0; \ + }while(0) + +/* Sets a string value, checking it hasn't been set already. */ +#define SAVESTRING(what,loc,val) do{ \ + savestring(DPC, what " respecified", &DPC->disk->loc, (val)); \ + }while(0) + + +static void +savestring(DiskParseContext *dpc, + const char *what_respecified, + char **update, + const char *value) +{ + if (*update) { + if (**update) { + xlu__disk_err(dpc, value, what_respecified); + return; + } + + free(*update); /* do not complain about overwriting empty strings */ + } + + *update = strdup(value); +} + +#define DPC dpc /* our convention in lexer helper functions */ + +/* Sets ->readwrite from the string. This ought to be an enum, perhaps. */ +static void +setaccess(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "r") || STREQ(str, "ro")) { + dpc->disk->src->readonly = 1; + } else if (STREQ(str, "w!") || STREQ(str, "!")) { + dpc->disk->src->shared = 1; + } else { + xlu__disk_err(dpc,str,"unknown value for access"); + } +} + +/* Sets ->format from the string. IDL should provide something for this. */ +static void +setformat(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW); + else if (STREQ(str, "raw")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_RAW); + else if (STREQ(str, "qcow")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW); + else if (STREQ(str, "qcow2")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_QCOW2); + else if (STREQ(str, "vhd")) + virDomainDiskSetFormat(dpc->disk, VIR_STORAGE_FILE_VHD); + else xlu__disk_err(dpc, str, "unknown value for format"); +} + + +/* Sets ->backend from the string. IDL should provide something for this. */ +static void +setdrivertype(DiskParseContext *dpc, const char *str) +{ + if (STREQ(str, "phy")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "phy")); + else if (STREQ(str, "tap")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "tap")); + else if (STREQ(str, "qdisk")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "qemu")); + else if (STREQ(str, "")) + ignore_value(virDomainDiskSetDriver(dpc->disk, "phy")); + else + xlu__disk_err(dpc, str, "unknown value for backendtype"); +} + + +/* Handles a vdev positional parameter which includes a devtype. */ +static int +vdev_and_devtype(DiskParseContext *dpc, char *str) +{ + /* returns 1 if it was <vdev>:<devtype>, 0 (doing nothing) otherwise */ + char *colon = strrchr(str, ':'); + if (!colon) + return 0; + + *colon++ = 0; + SAVESTRING("vdev", dst, str); + + if (STREQ(colon,"cdrom")) { + DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; + } else if (STREQ(colon, "disk")) { + DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; + } else { + xlu__disk_err(DPC, colon, "unknown deprecated type"); + } + return 1; +} + +#undef DPC /* needs to be defined differently the actual lexer */ +#define DPC ((DiskParseContext*)yyextra) + +%} + +%option warn +%option nodefault +%option batch +%option 8bit +%option noyywrap +%option reentrant +%option prefix="xlu__disk_yy" +%option nounput + +%x LEXERR + +%% + + /*----- the scanner rules which do the parsing -----*/ + +[ \t\n]+/([^ \t\n].*)? { /* ignore whitespace before parameters */ } + + /* ordinary parameters setting enums or strings */ + +format=[^,]*,? { STRIP(','); setformat(DPC, FROMEQUALS); } + +cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } +devtype=cdrom,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; } +devtype=disk,? { DPC->disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; } +devtype=[^,]*,? { xlu__disk_err(DPC, yytext,"unknown value for type"); } + +access=[^,]*,? { STRIP(','); setaccess(DPC, FROMEQUALS); } +backendtype=[^,]*,? { STRIP(','); setdrivertype(DPC, FROMEQUALS); } + +vdev=[^,]*,? { STRIP(','); SAVESTRING("vdev", dst, FROMEQUALS); } + + /* the target magic parameter, eats the rest of the string */ + +target=.* { STRIP(','); SAVESTRING("target", src->path, FROMEQUALS); } + + /* unknown parameters */ + +[a-z][-a-z0-9]*=[^,],? { xlu__disk_err(DPC, yytext, "unknown parameter"); } + + /* the "/.*" in these patterns ensures that they count as if they + * matched the whole string, so these patterns take precedence */ + +(raw|qcow2?|vhd):/.* { + STRIP(':'); + DPC->had_depr_prefix=1; + setformat(DPC, yytext); + } + +tapdisk:/.* { DPC->had_depr_prefix=1; } +tap2?:/.* { DPC->had_depr_prefix=1; } +aio:/.* { DPC->had_depr_prefix=1; } +ioemu:/.* { DPC->had_depr_prefix=1; } +file:/.* { DPC->had_depr_prefix=1; } +phy:/.* { DPC->had_depr_prefix=1; } +[a-z][a-z0-9]*:/([^a-z0-9].*)? { + xlu__disk_err(DPC, yytext, "unknown deprecated disk prefix"); + return 0; + } + + /* positional parameters */ + +[^=,]*,|[^=,]+,? { + STRIP(','); + + if (DPC->err) { + /* previous errors may just lead to subsequent ones */ + } else if (!DPC->disk->src->path) { + SAVESTRING("target", src->path, yytext); + } else if (DPC->disk->src->format == VIR_STORAGE_FILE_LAST){ + setformat(DPC, yytext); + } + else if (!DPC->disk->dst) { + if (!vdev_and_devtype(DPC, yytext)) + SAVESTRING("vdev", dst, yytext); + } else if (!DPC->access_set) { + DPC->access_set = 1; + setaccess(DPC, yytext); + } else { + xlu__disk_err(DPC, yytext, "too many positional parameters"); + return 0; /* don't print any more errors */ + } +} + +. { + BEGIN(LEXERR); + yymore(); +} +<LEXERR>.* { + xlu__disk_err(DPC, yytext, "bad disk syntax"); + return 0; +} diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index d71dd07..e7545b9 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -1804,7 +1804,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..9684c4c --- /dev/null +++ b/src/xenconfig/xen_xl.c @@ -0,0 +1,479 @@ +/* + * xen_xl.c: Xen XL parsing functions + * + * 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> + */ +#include <config.h> +#include <assert.h> +#include "virconf.h" +#include "virerror.h" +#include "domain_conf.h" +#include "viralloc.h" +#include "virstring.h" +#include "xen_xl.h" +#include "libxlu_disk_l.h" +#include "libxlu_disk_i.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +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; +} + + + +void +xlu__disk_err(DiskParseContext *dpc, + const char *erroneous, + const char *message) +{ + /*virReportError(VIR_ERR_INTERNAL_ERROR, + "%s: config parsing error in disk specification: %s" + "%s%s" + " in `%s'\n", + message, + erroneous?": near `":"", erroneous?erroneous:"", erroneous?"'":"", + dpc->spec); + if (!dpc->err) + dpc->err= EINVAL; + */ +} + + +static int +dpc_prep(DiskParseContext *dpc, const char *spec) +{ + int e; + dpc->spec = spec; + + e = xlu__disk_yylex_init_extra(dpc, &dpc->scanner); + if (e) + goto fail; + + dpc->buf = xlu__disk_yy_scan_bytes(spec, strlen(spec), dpc->scanner); + if (!dpc->buf) { + e = ENOMEM; + goto fail; + } + + return 0; + + fail: + virReportError(VIR_ERR_INTERNAL_ERROR, "cannot init disk scanner: %s\n", + strerror(errno)); + return e; +} + + +static void +dpc_dispose(DiskParseContext *dpc) +{ + virDomainDiskDefFree(dpc->disk); + + if (dpc->buf) { + xlu__disk_yy_delete_buffer(dpc->buf, dpc->scanner); + dpc->buf = 0; + } + if (dpc->scanner) { + xlu__disk_yylex_destroy(dpc->scanner); + dpc->scanner = 0; + } +} + +/* + * positional parameters + * (If the <diskspec> strings are not separated by "=" + * the string is split following ',' and assigned to + * the following options in the following order) + * target,format,vdev,access + * ================================================================ + * + * The parameters below cannot be specified as positional parameters: + * + * other parameters + * devtype = <devtype> + * backendtype = <backend-type> + * parameters not taken care of + * backend = <domain-name> + * script = <script> + * direct-io-safe + * + * ================================================================ + * The parser does not take any deprecated parameters + * + * For more information refer to /xen/docs/misc/xl-disk-configuration.txt + */ +static int +xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) +{ + int e; + DiskParseContext dpc; + + virConfValuePtr list = virConfGetValue(conf, "disk"); + dpc.conf = conf; + dpc.scanner = 0; + memset(&dpc, 0, sizeof(dpc)); + + if (list && list->type == VIR_CONF_LIST) { + list = list->list; + while (list) { + char *specs = list->str; + dpc.spec = specs; + + if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) + goto skipdisk; + + if (!(dpc.disk = virDomainDiskDefNew())) + return -1; + dpc.disk->src->readonly = 0; + dpc.disk->src->format = VIR_STORAGE_FILE_LAST; + + e = dpc_prep(&dpc, specs); + if (e) { + dpc.err = e; + } + xlu__disk_yylex(dpc.scanner); + + if (dpc.err) { + dpc_dispose(&dpc); + } + if (dpc.disk->src->format == VIR_STORAGE_FILE_LAST) { + dpc.disk->src->format = VIR_STORAGE_FILE_RAW; + } + + if (dpc.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + dpc.disk->removable = true; + dpc.disk->src->readonly = true; + if (!dpc.disk->src->path || STREQ(dpc.disk->src->path, "")) + dpc.disk->src->format = VIR_STORAGE_FILE_NONE; + } + + if (STRPREFIX(dpc.disk->dst, "xvd") || !STREQ(def->os.type, "hvm")) { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_XEN; + } else if (STRPREFIX(dpc.disk->dst, "sd")) { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; + } else { + dpc.disk->bus = VIR_DOMAIN_DISK_BUS_IDE; + } + + if (!(virDomainDiskGetDriver(dpc.disk))) + ignore_value(virDomainDiskSetDriver(dpc.disk, "phy")); + + virDomainDiskSetType(dpc.disk, STREQ(virDomainDiskGetDriver(dpc.disk), "phy") ? + VIR_STORAGE_TYPE_BLOCK : + VIR_STORAGE_TYPE_FILE); + if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, dpc.disk) < 0) + return -1; +skipdisk: + list = list->next; + virDomainDiskDefFree(dpc.disk); + dpc.disk = NULL; + } + + } + return 0; +} + + +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); + + /* 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 (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + virBufferAddLit(&buf, "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) +{ + virConfValuePtr diskVal = NULL; + size_t i = 0; + + 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) { + int ret = virConfSetValue(conf, "disk", diskVal); + diskVal = NULL; + if (ret < 0) + goto cleanup; + } + + return 0; + + cleanup: + virConfFreeValue(diskVal); + return 0; +} + + +static int +xenFormatXLSpice(virConfPtr conf, virDomainDefPtr def) +{ + const char *listenAddr = NULL; + + if (STREQ(def->os.type, "hvm")) { /*save's CPU :-) */ + 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, "spice_mouse_agent", + 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..d60fe5e --- /dev/null +++ b/src/xenconfig/xen_xl.h @@ -0,0 +1,29 @@ +/* + * xen_xl.h: Xen XL parsing functions + * + * 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 _XEN_XL_H_ +# define _XEN_XL_H_ + +# include "xen_common.h" + +virDomainDefPtr xenParseXL(virConfPtr conn, virCapsPtr caps, + int xendConfigVersion); +virConfPtr xenFormatXL(virDomainDefPtr def, + virConnectPtr, int xendConfigVersion); +#endif /* _XEN_XL_H_ */

On 09/11/2014 06:14 PM, Jim Fehlig wrote:
But also as mentioned before, I can't figure out how to convince automake to tell flex to generate the header file as well as the .c file.
Eric, do you have any experience with automake and flex? The following thread makes it sound as though automake supports flex's '--header-file=' option, but I can't find any hint on how to make it work
http://lists.gnu.org/archive/html/bug-automake/2012-08/msg00069.html
Quick reply here to acknowledge that you're waiting on me, although a more detailed reply may take me a few days... I haven't personally written a makefile with flex, but know that coreutils is such a project, so I plan to research how it gets things to work. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Hmm, any consensus on this? On Fri, Sep 12, 2014 at 4:17 PM, Eric Blake <eblake@redhat.com> wrote:
On 09/11/2014 06:14 PM, Jim Fehlig wrote:
But also as mentioned before, I can't figure out how to convince automake to tell flex to generate the header file as well as the .c file.
Eric, do you have any experience with automake and flex? The following thread makes it sound as though automake supports flex's '--header-file=' option, but I can't find any hint on how to make it work
http://lists.gnu.org/archive/html/bug-automake/2012-08/msg00069.html
Quick reply here to acknowledge that you're waiting on me, although a more detailed reply may take me a few days...
I haven't personally written a makefile with flex, but know that coreutils is such a project, so I plan to research how it gets things to work.
-- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

David kiarie wrote:
Hmm, any consensus on this?
I looked at coreutils following Eric's suggestion, but didn't notice any use of flex. I went back to the automake documented approach [1] and peeked at the resulting generated files. src/Makefile.in contains LEX_OUTPUT_ROOT = lex.yy LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) .l.c: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) which during an actual make produces /bin/sh ../build-aux/ylwrap xenconfig/libxlu_disk_l.l lex.yy.c xenconfig/libxlu_disk_l.c -- flex But later the build fails with CC xenconfig/libvirt_xenconfig_la-xen_xl.lo xenconfig/xen_xl.c:28:27: fatal error: libxlu_disk_l.h: No such file or directory #include "libxlu_disk_l.h" Which is the problem I mentioned earlier in the thread about flex not generating a header file. I naively tried hacking '--header-file' into AM_LFLAGS (e.g. AM_LFLAGS=--header-file=$*.h), but flex wasn't happy with that make[2]: Entering directory `libvirt/src' /bin/sh ../build-aux/ylwrap xenconfig/libxlu_disk_l.l lex.yy.c xenconfig/libxlu_disk_l.c -- flex --header-file=xenconfig/libxlu_disk_l.h flex: fatal internal error, freopen(headerfilename) failed I banged my head on this for a while but couldn't find a resolution :-/. The alternate approach is to use hand-crafted rules in src/Makefile.am, as you've done. I'd prefer something a bit more generic like %.c %.h:: %.l @rm -f $*.[ch] $(AM_V_GEN)$(LEX) --header-file=$*.h --outfile=$*.c $< Which does work but has the two issues we discussed earlier: - warning flags need relaxed when compiling the generated files - generated files need to be excluded from syntax-check The second issue is trivial, and although not obvious to me, I think there are several devs on the list that can give hints. Regards, Jim [1] http://www.gnu.org/software/automake/manual/html_node/Yacc-and-Lex.html
On Fri, Sep 12, 2014 at 4:17 PM, Eric Blake <eblake@redhat.com> wrote:
On 09/11/2014 06:14 PM, Jim Fehlig wrote:
But also as mentioned before, I can't figure out how to convince automake to tell flex to generate the header file as well as the .c file.
Eric, do you have any experience with automake and flex? The following thread makes it sound as though automake supports flex's '--header-file=' option, but I can't find any hint on how to make it work
http://lists.gnu.org/archive/html/bug-automake/2012-08/msg00069.html
Quick reply here to acknowledge that you're waiting on me, although a more detailed reply may take me a few days...
I haven't personally written a makefile with flex, but know that coreutils is such a project, so I plan to research how it gets things to work.
-- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

Integrate the xl parser into the xenlight driver Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> --- src/libxl/libxl_driver.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 67fd7bc6..515ea4d 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" @@ -2217,7 +2219,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; @@ -2244,7 +2256,7 @@ libxlConnectDomainXMLFromNative(virConnectPtr conn, goto cleanup; } - xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE); + xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE); cleanup: virDomainDefFree(def); @@ -2272,21 +2284,31 @@ libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat, if (virConnectDomainXMLToNativeEnsureACL(conn) < 0) goto cleanup; - if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { + if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) { + if (!(def = virDomainDefParseString(domainXml, + cfg->caps, driver->xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + if (!(conf = xenFormatXL(def, conn, cfg->verInfo->xen_version_major))) + goto cleanup; + } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { + 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))) + goto cleanup; + } else { + 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))) - goto cleanup; - if (VIR_ALLOC_N(ret, len) < 0) goto cleanup; -- 1.8.4.5

add tests for the xen_xl config parser Signed-off-by: Kiarie Kahurani <davidkiarie4@gmail.com> --- tests/Makefile.am | 9 +- tests/testutilsxen.c | 50 ++++++++ tests/testutilsxen.h | 9 +- tests/xlconfigdata/test-new-disk.cfg | 27 +++++ tests/xlconfigdata/test-new-disk.xml | 45 +++++++ tests/xlconfigdata/test-spice.cfg | 32 +++++ tests/xlconfigdata/test-spice.xml | 45 +++++++ tests/xlconfigtest.c | 224 +++++++++++++++++++++++++++++++++++ 8 files changed, 439 insertions(+), 2 deletions(-) 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 diff --git a/tests/Makefile.am b/tests/Makefile.am index d6c3cfb..82b0099 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -136,6 +136,7 @@ EXTRA_DIST = \ vmx2xmldata \ xencapsdata \ xmconfigdata \ + xlconfigdata \ xml2sexprdata \ xml2vmxdata \ vmwareverdata \ @@ -220,7 +221,8 @@ ssh_LDADD = $(COVERAGE_LDFLAGS) if WITH_XEN test_programs += xml2sexprtest sexpr2xmltest \ - xmconfigtest xencapstest statstest reconnect + xmconfigtest xencapstest statstest reconnect \ + xlconfigtest endif WITH_XEN if WITH_QEMU test_programs += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \ @@ -468,6 +470,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..d83c181 --- /dev/null +++ b/tests/xlconfigdata/test-new-disk.cfg @@ -0,0 +1,27 @@ +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" +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" ] +parallel = "none" +serial = "none" +disk = [ "/dev/HostVG/XenGuest2,raw,hda,w,", "/root/boot.iso,raw,hdc,w," ] diff --git a/tests/xlconfigdata/test-new-disk.xml b/tests/xlconfigdata/test-new-disk.xml new file mode 100644 index 0000000..504d4df --- /dev/null +++ b/tests/xlconfigdata/test-new-disk.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='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..b966c15 --- /dev/null +++ b/tests/xlconfigtest.c @@ -0,0 +1,224 @@ +/* + * xlconfigtest.c: Test backend for xl_internal config file handling + * + * Copyright (C) 2007, 2010-2011, 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * 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

Aah, just noticed the tests are not working On Thu, Sep 11, 2014 at 7:10 AM, Kiarie Kahurani <davidkiarie4@gmail.com> wrote:
Kiarie Kahurani (4): src/xenconfig: Export helper functions src/xenconfig: Xen-xl parser src/xenconfig: Introduce xen-xl on virsh command line tests: Tests for the xen-xl parser
configure.ac | 7 + src/Makefile.am | 21 +- src/libvirt_xenconfig.syms | 4 + src/libxl/libxl_driver.c | 46 +++- src/xenconfig/libxlu_disk_i.h | 28 ++ src/xenconfig/libxlu_disk_l.l | 259 +++++++++++++++++++ src/xenconfig/xen_common.c | 147 +++++------ src/xenconfig/xen_common.h | 24 +- src/xenconfig/xen_xl.c | 479 +++++++++++++++++++++++++++++++++++ src/xenconfig/xen_xl.h | 29 +++ tests/Makefile.am | 9 +- tests/testutilsxen.c | 50 ++++ tests/testutilsxen.h | 9 +- tests/xlconfigdata/test-new-disk.cfg | 27 ++ tests/xlconfigdata/test-new-disk.xml | 45 ++++ tests/xlconfigdata/test-spice.cfg | 32 +++ tests/xlconfigdata/test-spice.xml | 45 ++++ tests/xlconfigtest.c | 224 ++++++++++++++++ 18 files changed, 1389 insertions(+), 96 deletions(-) create mode 100644 src/xenconfig/libxlu_disk_i.h create mode 100644 src/xenconfig/libxlu_disk_l.l 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
Changes in V1
-introduced flex for xl disk format parsing
Changes in V2
-changed ot use AC_PROG_LEX in configure.ac -got rid of unused data files
Not done
-compile the generated file using global compiler flags as it has unused parameters
-- 1.8.4.5
participants (5)
-
David Kiarie
-
David kiarie
-
Eric Blake
-
Jim Fehlig
-
Kiarie Kahurani