/*
* xen_xl.c: Xen XL parsing functions
*
* Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* .
*
* Author: Kiarie Kahurani
* Author: Jim Fehlig
*/
#include
#include
#include "virconf.h"
#include "virerror.h"
#include "virlog.h"
#include "domain_conf.h"
#include "viralloc.h"
#include "virstring.h"
#include "virstoragefile.h"
#include "xen_xl.h"
#include "libxl_capabilities.h"
#define VIR_FROM_THIS VIR_FROM_XENXL
VIR_LOG_INIT("xen.xen_xl");
/*
* Xen provides a libxl utility library, with several useful functions,
* specifically xlu_disk_parse for parsing xl disk config strings.
* Although the libxlutil library is installed, until recently the
* corresponding header file wasn't. Use the header file if detected during
* configure, otherwise provide extern declarations for any functions used.
*/
#ifdef HAVE_LIBXLUTIL_H
# include
#else
typedef struct XLU_Config XLU_Config;
extern XLU_Config *xlu_cfg_init(FILE *report,
const char *report_filename);
extern void xlu_cfg_destroy(XLU_Config*);
extern int xlu_disk_parse(XLU_Config *cfg,
int nspecs,
const char *const *specs,
libxl_device_disk *disk);
#endif
static int xenParseCmdline(virConfPtr conf, char **r_cmdline)
{
char *cmdline = NULL;
const char *root, *extra, *buf;
if (xenConfigGetString(conf, "cmdline", &buf, NULL) < 0)
return -1;
if (xenConfigGetString(conf, "root", &root, NULL) < 0)
return -1;
if (xenConfigGetString(conf, "extra", &extra, NULL) < 0)
return -1;
if (buf) {
if (VIR_STRDUP(cmdline, buf) < 0)
return -1;
if (root || extra)
VIR_WARN("ignoring root= and extra= in favour of cmdline=");
} else {
if (root && extra) {
if (virAsprintf(&cmdline, "root=%s %s", root, extra) < 0)
return -1;
} else if (root) {
if (virAsprintf(&cmdline, "root=%s", root) < 0)
return -1;
} else if (extra) {
if (VIR_STRDUP(cmdline, extra) < 0)
return -1;
}
}
*r_cmdline = cmdline;
return 0;
}
static int
xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps)
{
size_t i;
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
const char *bios;
const char *boot;
if (xenConfigGetString(conf, "bios", &bios, NULL) < 0)
return -1;
if (bios && STREQ(bios, "ovmf")) {
if (VIR_ALLOC(def->os.loader) < 0)
return -1;
def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH;
def->os.loader->readonly = VIR_TRISTATE_BOOL_YES;
if (VIR_STRDUP(def->os.loader->path,
LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0)
return -1;
} else {
for (i = 0; i < caps->nguests; i++) {
if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM &&
caps->guests[i]->arch.id == def->os.arch) {
if (VIR_ALLOC(def->os.loader) < 0 ||
VIR_STRDUP(def->os.loader->path,
caps->guests[i]->arch.defaultInfo.loader) < 0)
return -1;
}
}
}
#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
return -1;
if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
return -1;
if (xenParseCmdline(conf, &def->os.cmdline) < 0)
return -1;
#endif
if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
return -1;
for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
switch (boot[i]) {
case 'a':
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
break;
case 'd':
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
break;
case 'n':
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
break;
case 'c':
default:
def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
break;
}
def->os.nBootDevs++;
}
} else {
if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
return -1;
if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
return -1;
if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
return -1;
if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
return -1;
if (xenParseCmdline(conf, &def->os.cmdline) < 0)
return -1;
}
return 0;
}
static int
xenParseXLSpice(virConfPtr conf, virDomainDefPtr def)
{
virDomainGraphicsDefPtr graphics = NULL;
unsigned long port;
char *listenAddr = NULL;
int val;
if (def->os.type == VIR_DOMAIN_OSTYPE_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 (virDomainGraphicsListenAppendAddress(graphics, listenAddr) < 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 (xenConfigCopyString(conf, "spicepasswd",
&graphics->data.spice.auth.passwd) < 0)
goto cleanup;
}
if (xenConfigGetBool(conf, "spiceagent_mouse",
&val, 0) < 0)
goto cleanup;
if (val) {
graphics->data.spice.mousemode =
VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT;
} else {
graphics->data.spice.mousemode =
VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER;
}
if (xenConfigGetBool(conf, "spice_clipboard_sharing", &val, 0) < 0)
goto cleanup;
if (val)
graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_YES;
else
graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_NO;
if (VIR_ALLOC_N(def->graphics, 1) < 0)
goto cleanup;
def->graphics[0] = graphics;
def->ngraphics = 1;
}
}
return 0;
cleanup:
VIR_FREE(listenAddr);
virDomainGraphicsDefFree(graphics);
return -1;
}
static int
xenParseXLDiskSrc(virDomainDiskDefPtr disk, char *srcstr)
{
char *tmpstr = NULL;
int ret = -1;
if (STRPREFIX(srcstr, "rbd:")) {
if (!(tmpstr = virStringReplace(srcstr, "\\\\", "\\")))
goto cleanup;
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_NETWORK);
disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD;
ret = virStorageSourceParseRBDColonString(tmpstr, disk->src);
} else {
if (virDomainDiskSetSource(disk, srcstr) < 0)
goto cleanup;
ret = 0;
}
cleanup:
VIR_FREE(tmpstr);
return ret;
}
/*
* For details on xl disk config syntax, see
* docs/misc/xl-disk-configuration.txt in the Xen sources. The important
* section of text is:
*
* More formally, the string is a series of comma-separated keyword/value
* pairs, flags and positional parameters. Parameters which are not bare
* keywords and which do not contain "=" symbols are assigned to the
* so-far-unspecified positional parameters, in the order below. The
* positional parameters may also be specified explicitly by name.
*
* Each parameter may be specified at most once, either as a positional
* parameter or a named parameter. Default values apply if the parameter
* is not specified, or if it is specified with an empty value (whether
* positionally or explicitly).
*
* Whitespace may appear before each parameter and will be ignored.
*
* The order of the positional parameters mentioned in the quoted text is:
*
* target,format,vdev,access
*
* The following options must be specified by key=value:
*
* devtype=
* backendtype=
*
* The following options are currently not supported:
*
* backend=
* script=