[libvirt] [PATCH V2 2/4] src/xenconfig: Xen-xl parser

Jim Fehlig jfehlig at suse.com
Fri Sep 12 00:14:12 UTC 2014


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 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 "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 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;
> +            }
> +
> +            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 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