[libvirt] [PATCH V1 2/4] src/xenconfig: Xen-xl parser
Jim Fehlig
jfehlig at suse.com
Tue Sep 9 22:17:42 UTC 2014
Kiarie Kahurani wrote:
> 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 at gmail.com>
> ---
> configure.ac | 5 +-
> src/Makefile.am | 21 +-
> src/libvirt_xenconfig.syms | 4 +
> src/xenconfig/libxlu_disk_i.h | 28 +++
> src/xenconfig/libxlu_disk_l.l | 292 ++++++++++++++++++++++++++
> src/xenconfig/xen_common.c | 3 +-
> src/xenconfig/xen_xl.c | 476 ++++++++++++++++++++++++++++++++++++++++++
> src/xenconfig/xen_xl.h | 29 +++
> 8 files changed, 852 insertions(+), 6 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..a60d0ad 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2176,7 +2176,10 @@ AC_PATH_PROG([PERL], [perl])
> if test -z "$PERL"; then
> AC_MSG_ERROR([Failed to find perl.])
> fi
> -
> +AC_PATH_PROG([FLEX], [flex])
> +if test -z "$FLEX"; then
> + AC_MSG_ERROR([failed to find flex.])
> +fi
>
According to the automake manual [1], AM_PROG_FLEX is recommended in
configure.ac
"If a |lex| source file is seen, then your configure.ac must define the
variable |LEX|. You can use |AC_PROG_LEX| to do this (see Particular
Program Checks in The Autoconf Manual), but using |AM_PROG_LEX| macro
(see Macros) is recommended."
> 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..38560ce 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) \
>
Hmm, that won't fly. I assume you made this change to squelch warnings
when compiling the generated file?
> $(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)$(FLEX) --outfile=$(srcdir)/xenconfig/libxlu_disk_l.c \
> + --header-file=$(srcdir)/xenconfig/libxlu_disk_l.h \
> + $(srcdir)/xenconfig/libxlu_disk_l.l
> +
> +CLEANFILES += $(XENCONFIG_GENERATED)
>
I suppose this is one way to generate the files with flex, but according
to the manual it should be something like
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
However, I can't nudge flex to generate the header file with this
approach. I tried adding 'AM_LFLAGS = --header-file' after
BUILT_SOURCES, but still no header is generated. I haven't had much luck
searching for an example doing this in the automake framework. Eric has
a lot of expertise in this area and might have suggestions.
Regards,
Jim
[1] http://www.gnu.org/software/automake/manual/html_node/Yacc-and-Lex.html
> +
> 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..7b6893b
> --- /dev/null
> +++ b/src/xenconfig/libxlu_disk_l.l
> @@ -0,0 +1,292 @@
> +/* -*- fundamental -*- */
> +/*
> + * libxlu_disk_l.l - parser for disk specification strings
> + *
> + * Copyright (C) 2011 Citrix Ltd.
> + * Author Ian Jackson <ian.jackson at 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 <stdarg.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)
> +
> +int
> +asprintf(char **ret, const char *format, ...)
> +{
> + va_list ap;
> +
> + *ret = NULL; /* Ensure value can be passed to free() */
> +
> + va_start(ap, format);
> + int count = vsnprintf(NULL, 0, format, ap);
> + va_end(ap);
> +
> + if (count >= 0)
> + {
> + char* buffer = malloc(count + 1);
> + if (buffer == NULL)
> + return -1;
> +
> + va_start(ap, format);
> + count = vsnprintf(buffer, count + 1, format, ap);
> + va_end(ap);
> +
> + if (count < 0)
> + {
> + free(buffer);
> + return count;
> + }
> + *ret = buffer;
> + }
> +
> + return count;
> +}
> +
> +
> +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..3949b37 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..f491958
> --- /dev/null
> +++ b/src/xenconfig/xen_xl.c
> @@ -0,0 +1,476 @@
> +/*
> + * 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 at 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;
> + }
> +
> + 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 at 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_ */
>
More information about the libvir-list
mailing list