2011-02-21 13:40:08 +00:00
|
|
|
/*
|
|
|
|
* xen_sxpr.c: Xen SEXPR parsing functions
|
|
|
|
*
|
2013-03-26 11:21:33 +00:00
|
|
|
* Copyright (C) 2010-2013 Red Hat, Inc.
|
2011-02-21 13:40:08 +00:00
|
|
|
* Copyright (C) 2011 Univention GmbH
|
|
|
|
* Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2011-02-21 13:40:08 +00:00
|
|
|
*
|
|
|
|
* Author: Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
* Author: Daniel Veillard <veillard@redhat.com>
|
|
|
|
* Author: Markus Groß <gross@univention.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2011-02-21 13:40:08 +00:00
|
|
|
#include "verify.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-02-21 13:40:08 +00:00
|
|
|
#include "count-one-bits.h"
|
|
|
|
#include "xenxs_private.h"
|
|
|
|
#include "xen_sxpr.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/* Get a domain id from a S-expression string */
|
2011-02-21 13:40:08 +00:00
|
|
|
int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion)
|
|
|
|
{
|
|
|
|
struct sexpr *root = string2sexpr(sexpr);
|
|
|
|
|
|
|
|
if (!root)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
int id = xenGetDomIdFromSxpr(root, xendConfigVersion);
|
|
|
|
sexpr_free(root);
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/* Get a domain id from a S-expression */
|
2011-02-21 13:40:08 +00:00
|
|
|
int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion)
|
|
|
|
{
|
|
|
|
int id = -1;
|
|
|
|
const char * tmp = sexpr_node(root, "domain/domid");
|
2012-01-31 17:08:09 +00:00
|
|
|
if (tmp == NULL && xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { /* domid was mandatory */
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, missing id"));
|
2011-02-21 13:40:08 +00:00
|
|
|
} else {
|
|
|
|
id = tmp ? sexpr_int(root, "domain/domid") : -1;
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************
|
|
|
|
******
|
2012-01-17 08:26:13 +00:00
|
|
|
****** Parsing of S-Expression into virDomainDef objects
|
2011-02-21 13:40:08 +00:00
|
|
|
******
|
|
|
|
*****************************************************************/
|
|
|
|
|
|
|
|
/**
|
2012-01-17 08:26:13 +00:00
|
|
|
* xenParseSxprOS:
|
2011-02-21 13:40:08 +00:00
|
|
|
* @node: the root of the parsed S-Expression
|
|
|
|
* @def: the domain config
|
2012-01-17 08:26:13 +00:00
|
|
|
* @hvm: true or 1 if node contains HVM S-Expression
|
2011-02-21 13:40:08 +00:00
|
|
|
*
|
|
|
|
* Parse the xend sexp for description of os and append it to buf.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success and -1 in case of error
|
|
|
|
*/
|
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprOS(const struct sexpr *node,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
int hvm)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
if (hvm) {
|
|
|
|
if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (def->os.loader == NULL) {
|
|
|
|
if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (def->os.loader == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, missing HVM loader"));
|
2012-03-22 11:33:35 +00:00
|
|
|
return -1;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If HVM kenrel == loader, then old xend, so kill off kernel */
|
|
|
|
if (hvm &&
|
|
|
|
def->os.kernel &&
|
|
|
|
STREQ(def->os.kernel, def->os.loader)) {
|
|
|
|
VIR_FREE(def->os.kernel);
|
|
|
|
}
|
2011-10-10 16:22:44 +00:00
|
|
|
/* Drop kernel argument that has no value */
|
|
|
|
if (hvm &&
|
|
|
|
def->os.kernel && *def->os.kernel == '\0' &&
|
|
|
|
def->os.loader) {
|
|
|
|
VIR_FREE(def->os.kernel);
|
|
|
|
}
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (!def->os.kernel &&
|
|
|
|
hvm) {
|
|
|
|
const char *boot = sexpr_node(node, "domain/image/hvm/boot");
|
|
|
|
if ((boot != NULL) && (boot[0] != 0)) {
|
|
|
|
while (*boot &&
|
|
|
|
def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
|
|
|
|
if (*boot == 'a')
|
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
|
|
|
|
else if (*boot == 'c')
|
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
|
|
|
|
else if (*boot == 'd')
|
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
|
|
|
|
else if (*boot == 'n')
|
|
|
|
def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
|
|
|
|
boot++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hvm &&
|
|
|
|
!def->os.kernel &&
|
|
|
|
!def->os.bootloader) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, missing kernel & bootloader"));
|
2011-02-21 13:40:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2013-07-04 10:19:27 +00:00
|
|
|
error:
|
2011-02-21 13:40:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenParseSxprChar:
|
|
|
|
* @value: A string describing a character device.
|
|
|
|
* @tty: the console pty path
|
|
|
|
*
|
|
|
|
* Parse the xend S-expression for description of a character device.
|
|
|
|
*
|
|
|
|
* Returns a character device object or NULL in case of failure.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainChrDefPtr
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprChar(const char *value,
|
|
|
|
const char *tty)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
const char *prefix;
|
|
|
|
char *tmp;
|
|
|
|
virDomainChrDefPtr def;
|
|
|
|
|
2011-04-14 16:05:14 +00:00
|
|
|
if (!(def = virDomainChrDefNew()))
|
2011-02-21 13:40:08 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
prefix = value;
|
|
|
|
|
|
|
|
if (value[0] == '/') {
|
|
|
|
def->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(def->source.data.file.path, value) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
} else {
|
|
|
|
if ((tmp = strchr(value, ':')) != NULL) {
|
|
|
|
*tmp = '\0';
|
|
|
|
value = tmp + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STRPREFIX(prefix, "telnet")) {
|
|
|
|
def->source.type = VIR_DOMAIN_CHR_TYPE_TCP;
|
|
|
|
def->source.data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
|
|
|
|
} else {
|
|
|
|
if ((def->source.type = virDomainChrTypeFromString(prefix)) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown chr device type '%s'"), prefix);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (def->source.type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(def->source.data.file.path, tty) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(def->source.data.file.path, value) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_TCP:
|
|
|
|
{
|
|
|
|
const char *offset = strchr(value, ':');
|
|
|
|
const char *offset2;
|
|
|
|
|
|
|
|
if (offset == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("malformed char device string"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset != value &&
|
2013-05-03 12:51:56 +00:00
|
|
|
VIR_STRNDUP(def->source.data.tcp.host, value, offset - value) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
offset2 = strchr(offset, ',');
|
2013-05-03 12:51:56 +00:00
|
|
|
offset++;
|
|
|
|
if (VIR_STRNDUP(def->source.data.tcp.service, offset,
|
2013-05-24 09:21:36 +00:00
|
|
|
offset2 ? offset2 - offset : -1) < 0)
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (offset2 && strstr(offset2, ",server"))
|
|
|
|
def->source.data.tcp.listen = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UDP:
|
|
|
|
{
|
|
|
|
const char *offset = strchr(value, ':');
|
|
|
|
const char *offset2, *offset3;
|
|
|
|
|
|
|
|
if (offset == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("malformed char device string"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset != value &&
|
2013-05-03 12:51:56 +00:00
|
|
|
VIR_STRNDUP(def->source.data.udp.connectHost, value, offset - value) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
offset2 = strchr(offset, '@');
|
|
|
|
if (offset2 != NULL) {
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRNDUP(def->source.data.udp.connectService,
|
|
|
|
offset + 1, offset2 - offset - 1) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
offset3 = strchr(offset2, ':');
|
|
|
|
if (offset3 == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("malformed char device string"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset3 > (offset2 + 1) &&
|
2013-05-03 12:51:56 +00:00
|
|
|
VIR_STRNDUP(def->source.data.udp.bindHost,
|
|
|
|
offset2 + 1, offset3 - offset2 - 1) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(def->source.data.udp.bindService, offset3 + 1) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
} else {
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(def->source.data.udp.connectService, offset + 1) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
{
|
|
|
|
const char *offset = strchr(value, ',');
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRNDUP(def->source.data.nix.path, value,
|
2013-05-24 09:21:36 +00:00
|
|
|
offset ? offset - value : -1) < 0)
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (offset != NULL &&
|
|
|
|
strstr(offset, ",server") != NULL)
|
|
|
|
def->source.data.nix.listen = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainChrDefFree(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
2011-02-21 13:40:08 +00:00
|
|
|
/**
|
2012-01-17 08:26:13 +00:00
|
|
|
* xenParseSxprDisks:
|
|
|
|
* @def: the domain config
|
|
|
|
* @root: root S-expression
|
|
|
|
* @hvm: true or 1 if node contains HVM S-Expression
|
2011-02-21 13:40:08 +00:00
|
|
|
* @xendConfigVersion: version of xend
|
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* This parses out block devices from the domain S-expression
|
2011-02-21 13:40:08 +00:00
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprDisks(virDomainDefPtr def,
|
|
|
|
const struct sexpr *root,
|
|
|
|
int hvm,
|
|
|
|
int xendConfigVersion)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
const struct sexpr *cur, *node;
|
|
|
|
virDomainDiskDefPtr disk = NULL;
|
|
|
|
|
|
|
|
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
node = cur->u.s.car;
|
|
|
|
/* Normally disks are in a (device (vbd ...)) block
|
|
|
|
but blktap disks ended up in a differently named
|
|
|
|
(device (tap ....)) block.... */
|
|
|
|
if (sexpr_lookup(node, "device/vbd") ||
|
|
|
|
sexpr_lookup(node, "device/tap") ||
|
|
|
|
sexpr_lookup(node, "device/tap2")) {
|
|
|
|
char *offset;
|
|
|
|
const char *src = NULL;
|
|
|
|
const char *dst = NULL;
|
|
|
|
const char *mode = NULL;
|
xen: fix PyGrub boot device order
When PyGrub is used as the bootloader in Xen, it gets passed the first
bootable disk. Xend supports a "bootable"-flag for this, which isn't
explicitly supported by libvirt.
When converting libvirt-xml to xen-sxpr the "bootable"-flag gets
implicitly set by xen.xend.XenConfig.device_add() for the first disk
(marked as "Compat hack -- mark first disk bootable").
When converting back xen-sxpr to libvirt-xml, the disks are returned in
the internal order used by Xend ignoring the "bootable"-flag, which
loses the original order. When the domain is then re-defined, the order
of disks is changed, which breaks PyGrub, since a different disk gets
passed.
When converting xen-sxpr to libvirt-xml, use the "bootable"-flag to
determine the first disk.
This isn't perfect, since several disks can be marked as bootable using
the Xend-API, but that is not supported by libvirt. In all known cases
relevant to libvirt exactly one disk is marked as bootable.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-10-12 08:26:46 +00:00
|
|
|
const char *bootable = NULL;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
/* Again dealing with (vbd...) vs (tap ...) differences */
|
|
|
|
if (sexpr_lookup(node, "device/vbd")) {
|
|
|
|
src = sexpr_node(node, "device/vbd/uname");
|
|
|
|
dst = sexpr_node(node, "device/vbd/dev");
|
|
|
|
mode = sexpr_node(node, "device/vbd/mode");
|
xen: fix PyGrub boot device order
When PyGrub is used as the bootloader in Xen, it gets passed the first
bootable disk. Xend supports a "bootable"-flag for this, which isn't
explicitly supported by libvirt.
When converting libvirt-xml to xen-sxpr the "bootable"-flag gets
implicitly set by xen.xend.XenConfig.device_add() for the first disk
(marked as "Compat hack -- mark first disk bootable").
When converting back xen-sxpr to libvirt-xml, the disks are returned in
the internal order used by Xend ignoring the "bootable"-flag, which
loses the original order. When the domain is then re-defined, the order
of disks is changed, which breaks PyGrub, since a different disk gets
passed.
When converting xen-sxpr to libvirt-xml, use the "bootable"-flag to
determine the first disk.
This isn't perfect, since several disks can be marked as bootable using
the Xend-API, but that is not supported by libvirt. In all known cases
relevant to libvirt exactly one disk is marked as bootable.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-10-12 08:26:46 +00:00
|
|
|
bootable = sexpr_node(node, "device/vbd/bootable");
|
2011-02-21 13:40:08 +00:00
|
|
|
} else if (sexpr_lookup(node, "device/tap2")) {
|
|
|
|
src = sexpr_node(node, "device/tap2/uname");
|
|
|
|
dst = sexpr_node(node, "device/tap2/dev");
|
|
|
|
mode = sexpr_node(node, "device/tap2/mode");
|
xen: fix PyGrub boot device order
When PyGrub is used as the bootloader in Xen, it gets passed the first
bootable disk. Xend supports a "bootable"-flag for this, which isn't
explicitly supported by libvirt.
When converting libvirt-xml to xen-sxpr the "bootable"-flag gets
implicitly set by xen.xend.XenConfig.device_add() for the first disk
(marked as "Compat hack -- mark first disk bootable").
When converting back xen-sxpr to libvirt-xml, the disks are returned in
the internal order used by Xend ignoring the "bootable"-flag, which
loses the original order. When the domain is then re-defined, the order
of disks is changed, which breaks PyGrub, since a different disk gets
passed.
When converting xen-sxpr to libvirt-xml, use the "bootable"-flag to
determine the first disk.
This isn't perfect, since several disks can be marked as bootable using
the Xend-API, but that is not supported by libvirt. In all known cases
relevant to libvirt exactly one disk is marked as bootable.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-10-12 08:26:46 +00:00
|
|
|
bootable = sexpr_node(node, "device/tap2/bootable");
|
2011-02-21 13:40:08 +00:00
|
|
|
} else {
|
|
|
|
src = sexpr_node(node, "device/tap/uname");
|
|
|
|
dst = sexpr_node(node, "device/tap/dev");
|
|
|
|
mode = sexpr_node(node, "device/tap/mode");
|
xen: fix PyGrub boot device order
When PyGrub is used as the bootloader in Xen, it gets passed the first
bootable disk. Xend supports a "bootable"-flag for this, which isn't
explicitly supported by libvirt.
When converting libvirt-xml to xen-sxpr the "bootable"-flag gets
implicitly set by xen.xend.XenConfig.device_add() for the first disk
(marked as "Compat hack -- mark first disk bootable").
When converting back xen-sxpr to libvirt-xml, the disks are returned in
the internal order used by Xend ignoring the "bootable"-flag, which
loses the original order. When the domain is then re-defined, the order
of disks is changed, which breaks PyGrub, since a different disk gets
passed.
When converting xen-sxpr to libvirt-xml, use the "bootable"-flag to
determine the first disk.
This isn't perfect, since several disks can be marked as bootable using
the Xend-API, but that is not supported by libvirt. In all known cases
relevant to libvirt exactly one disk is marked as bootable.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-10-12 08:26:46 +00:00
|
|
|
bootable = sexpr_node(node, "device/tap/bootable");
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(disk) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (dst == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, vbd has no dev"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src == NULL) {
|
|
|
|
/* There is a case without the uname to the CD-ROM device */
|
|
|
|
offset = strchr(dst, ':');
|
|
|
|
if (!offset ||
|
|
|
|
!hvm ||
|
|
|
|
STRNEQ(offset, ":cdrom")) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, vbd has no src"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src != NULL) {
|
|
|
|
offset = strchr(src, ':');
|
|
|
|
if (!offset) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot parse vbd filename, missing driver name"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-10-12 08:55:37 +00:00
|
|
|
if (sexpr_lookup(node, "device/tap2") &&
|
|
|
|
STRPREFIX(src, "tap:")) {
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->driverName, "tap2") < 0)
|
|
|
|
goto error;
|
2011-10-12 08:55:37 +00:00
|
|
|
} else {
|
|
|
|
if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-10-12 08:55:37 +00:00
|
|
|
if (virStrncpy(disk->driverName, src, offset-src,
|
|
|
|
(offset-src)+1) == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Driver name %s too big for destination"),
|
|
|
|
src);
|
2011-10-12 08:55:37 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
src = offset + 1;
|
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
if (STREQ(disk->driverName, "tap") ||
|
|
|
|
STREQ(disk->driverName, "tap2")) {
|
2012-10-15 21:47:42 +00:00
|
|
|
char *driverType = NULL;
|
|
|
|
|
2011-02-21 13:40:08 +00:00
|
|
|
offset = strchr(src, ':');
|
|
|
|
if (!offset) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot parse vbd filename, missing driver type"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRNDUP(driverType, src, offset - src) < 0)
|
|
|
|
goto error;
|
2012-10-15 21:47:42 +00:00
|
|
|
if (STREQ(driverType, "aio"))
|
|
|
|
disk->format = VIR_STORAGE_FILE_RAW;
|
|
|
|
else
|
|
|
|
disk->format =
|
|
|
|
virStorageFileFormatTypeFromString(driverType);
|
|
|
|
VIR_FREE(driverType);
|
|
|
|
if (disk->format <= 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2012-10-15 21:47:42 +00:00
|
|
|
_("Unknown driver type %s"), src);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
src = offset + 1;
|
|
|
|
/* Its possible to use blktap driver for block devs
|
|
|
|
too, but kinda pointless because blkback is better,
|
|
|
|
so we assume common case here. If blktap becomes
|
|
|
|
omnipotent, we can revisit this, perhaps stat()'ing
|
|
|
|
the src file in question */
|
|
|
|
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
} else if (STREQ(disk->driverName, "phy")) {
|
|
|
|
disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
|
|
|
} else if (STREQ(disk->driverName, "file")) {
|
|
|
|
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* No CDROM media so can't really tell. We'll just
|
|
|
|
call if a FILE for now and update when media
|
|
|
|
is inserted later */
|
|
|
|
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
}
|
|
|
|
|
2012-10-17 09:23:12 +00:00
|
|
|
if (STREQLEN(dst, "ioemu:", 6))
|
2011-02-21 13:40:08 +00:00
|
|
|
dst += 6;
|
|
|
|
|
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
|
|
|
/* New style disk config from Xen >= 3.0.3 */
|
2012-01-31 17:08:09 +00:00
|
|
|
if (xendConfigVersion >= XEND_CONFIG_VERSION_3_0_3) {
|
2011-02-21 13:40:08 +00:00
|
|
|
offset = strrchr(dst, ':');
|
|
|
|
if (offset) {
|
2012-10-17 09:23:12 +00:00
|
|
|
if (STREQ(offset, ":cdrom")) {
|
2011-02-21 13:40:08 +00:00
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
2012-10-17 09:23:12 +00:00
|
|
|
} else if (STREQ(offset, ":disk")) {
|
2011-02-21 13:40:08 +00:00
|
|
|
/* The default anyway */
|
|
|
|
} else {
|
|
|
|
/* Unknown, lets pretend its a disk too */
|
|
|
|
}
|
|
|
|
offset[0] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->dst, dst) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(disk->src, src) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (STRPREFIX(disk->dst, "xvd"))
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
|
|
|
|
else if (STRPREFIX(disk->dst, "hd"))
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
|
|
|
else if (STRPREFIX(disk->dst, "sd"))
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
|
|
|
|
else
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
|
|
|
|
|
|
|
if (mode &&
|
|
|
|
strchr(mode, 'r'))
|
2013-04-10 11:23:56 +00:00
|
|
|
disk->readonly = true;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (mode &&
|
|
|
|
strchr(mode, '!'))
|
2013-04-10 10:59:44 +00:00
|
|
|
disk->shared = true;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
xen: fix PyGrub boot device order
When PyGrub is used as the bootloader in Xen, it gets passed the first
bootable disk. Xend supports a "bootable"-flag for this, which isn't
explicitly supported by libvirt.
When converting libvirt-xml to xen-sxpr the "bootable"-flag gets
implicitly set by xen.xend.XenConfig.device_add() for the first disk
(marked as "Compat hack -- mark first disk bootable").
When converting back xen-sxpr to libvirt-xml, the disks are returned in
the internal order used by Xend ignoring the "bootable"-flag, which
loses the original order. When the domain is then re-defined, the order
of disks is changed, which breaks PyGrub, since a different disk gets
passed.
When converting xen-sxpr to libvirt-xml, use the "bootable"-flag to
determine the first disk.
This isn't perfect, since several disks can be marked as bootable using
the Xend-API, but that is not supported by libvirt. In all known cases
relevant to libvirt exactly one disk is marked as bootable.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2011-10-12 08:26:46 +00:00
|
|
|
/* re-order disks if there is a bootable device */
|
|
|
|
if (STREQ_NULLABLE(bootable, "1")) {
|
|
|
|
def->disks[def->ndisks++] = def->disks[0];
|
|
|
|
def->disks[0] = disk;
|
|
|
|
} else {
|
|
|
|
def->disks[def->ndisks++] = disk;
|
|
|
|
}
|
2011-02-21 13:40:08 +00:00
|
|
|
disk = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainDiskDefFree(disk);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/**
|
|
|
|
* xenParseSxprNets:
|
|
|
|
* @def: the domain config
|
|
|
|
* @root: root S-expression
|
|
|
|
*
|
|
|
|
* This parses out network devices from the domain S-expression
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprNets(virDomainDefPtr def,
|
|
|
|
const struct sexpr *root)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
virDomainNetDefPtr net = NULL;
|
|
|
|
const struct sexpr *cur, *node;
|
|
|
|
const char *tmp;
|
|
|
|
int vif_index = 0;
|
|
|
|
|
|
|
|
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
node = cur->u.s.car;
|
|
|
|
if (sexpr_lookup(node, "device/vif")) {
|
|
|
|
const char *tmp2, *model, *type;
|
|
|
|
tmp2 = sexpr_node(node, "device/vif/script");
|
|
|
|
tmp = sexpr_node(node, "device/vif/bridge");
|
|
|
|
model = sexpr_node(node, "device/vif/model");
|
|
|
|
type = sexpr_node(node, "device/vif/type");
|
|
|
|
|
|
|
|
if (VIR_ALLOC(net) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (tmp != NULL ||
|
|
|
|
(tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
|
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
|
|
|
|
/* XXX virtual network reverse resolve */
|
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(net->data.bridge.brname, tmp) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
VIR_STRDUP(net->script, tmp2) < 0)
|
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
tmp = sexpr_node(node, "device/vif/ip");
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(net->data.bridge.ipaddr, tmp) < 0)
|
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
} else {
|
|
|
|
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(net->script, tmp2) < 0)
|
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
tmp = sexpr_node(node, "device/vif/ip");
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(net->data.ethernet.ipaddr, tmp) < 0)
|
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp = sexpr_node(node, "device/vif/vifname");
|
2011-04-27 22:39:37 +00:00
|
|
|
/* If vifname is specified in xend config, include it in net
|
|
|
|
* definition regardless of domain state. If vifname is not
|
|
|
|
* specified, only generate one if domain is active (id != -1). */
|
|
|
|
if (tmp) {
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(net->ifname, tmp) < 0)
|
|
|
|
goto cleanup;
|
2011-04-27 22:39:37 +00:00
|
|
|
} else if (def->id != -1) {
|
|
|
|
if (virAsprintf(&net->ifname, "vif%d.%d", def->id, vif_index) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tmp = sexpr_node(node, "device/vif/mac");
|
|
|
|
if (tmp) {
|
2012-07-17 12:07:59 +00:00
|
|
|
if (virMacAddrParse(tmp, &net->mac) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("malformed mac address '%s'"), tmp);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(net->model, model) < 0)
|
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (!model && type && STREQ(type, "netfront") &&
|
|
|
|
VIR_STRDUP(net->model, "netfront") < 0)
|
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto cleanup;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
def->nets[def->nnets++] = net;
|
|
|
|
vif_index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virDomainNetDefFree(net);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/**
|
|
|
|
* xenParseSxprSound:
|
|
|
|
* @def: the domain config
|
|
|
|
* @str: comma separated list of sound models
|
|
|
|
*
|
|
|
|
* This parses out sound devices from the domain S-expression
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprSound(virDomainDefPtr def,
|
|
|
|
const char *str)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
if (STREQ(str, "all")) {
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
/*
|
2012-02-03 18:20:22 +00:00
|
|
|
* Special compatibility code for Xen with a bogus
|
2011-02-21 13:40:08 +00:00
|
|
|
* sound=all in config.
|
|
|
|
*
|
2011-08-23 17:02:02 +00:00
|
|
|
* NB deliberately, don't include all possible
|
2011-02-21 13:40:08 +00:00
|
|
|
* sound models anymore, just the 2 that were
|
|
|
|
* historically present in Xen's QEMU.
|
|
|
|
*
|
|
|
|
* ie just es1370 + sb16.
|
|
|
|
*
|
|
|
|
* Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->sounds,
|
|
|
|
VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1); i++) {
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainSoundDefPtr sound;
|
|
|
|
if (VIR_ALLOC(sound) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
sound->model = i;
|
|
|
|
def->sounds[def->nsounds++] = sound;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
char model[10];
|
|
|
|
const char *offset = str, *offset2;
|
|
|
|
|
|
|
|
do {
|
|
|
|
int len;
|
|
|
|
virDomainSoundDefPtr sound;
|
|
|
|
offset2 = strchr(offset, ',');
|
|
|
|
if (offset2)
|
|
|
|
len = (offset2 - offset);
|
|
|
|
else
|
|
|
|
len = strlen(offset);
|
|
|
|
if (virStrncpy(model, offset, len, sizeof(model)) == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Sound model %s too big for destination"),
|
|
|
|
offset);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(sound) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
|
|
|
|
VIR_FREE(sound);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
|
|
|
|
virDomainSoundDefFree(sound);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def->sounds[def->nsounds++] = sound;
|
|
|
|
offset = offset2 ? offset2 + 1 : NULL;
|
|
|
|
} while (offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/**
|
|
|
|
* xenParseSxprUSB:
|
|
|
|
* @def: the domain config
|
|
|
|
* @root: root S-expression
|
|
|
|
*
|
|
|
|
* This parses out USB devices from the domain S-expression
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprUSB(virDomainDefPtr def,
|
|
|
|
const struct sexpr *root)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
struct sexpr *cur, *node;
|
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
node = cur->u.s.car;
|
|
|
|
if (sexpr_lookup(node, "usbdevice")) {
|
|
|
|
tmp = sexpr_node(node, "usbdevice");
|
|
|
|
if (tmp && *tmp) {
|
|
|
|
if (STREQ(tmp, "tablet") ||
|
|
|
|
STREQ(tmp, "mouse")) {
|
|
|
|
virDomainInputDefPtr input;
|
|
|
|
if (VIR_ALLOC(input) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
input->bus = VIR_DOMAIN_INPUT_BUS_USB;
|
|
|
|
if (STREQ(tmp, "tablet"))
|
|
|
|
input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
|
|
|
|
else
|
|
|
|
input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
|
|
|
|
VIR_FREE(input);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
def->inputs[def->ninputs++] = input;
|
|
|
|
} else {
|
|
|
|
/* XXX Handle other non-input USB devices later */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
2013-07-04 10:19:27 +00:00
|
|
|
error:
|
2011-02-21 13:40:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* xenParseSxprGraphicsOld:
|
|
|
|
* @def: the domain config
|
|
|
|
* @root: root S-expression
|
|
|
|
* @hvm: true or 1 if root contains HVM S-Expression
|
|
|
|
* @xendConfigVersion: version of xend
|
|
|
|
* @vncport: VNC port number
|
|
|
|
*
|
|
|
|
* This parses out VNC devices from the domain S-expression
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprGraphicsOld(virDomainDefPtr def,
|
|
|
|
const struct sexpr *root,
|
|
|
|
int hvm,
|
|
|
|
int xendConfigVersion, int vncport)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
virDomainGraphicsDefPtr graphics = NULL;
|
|
|
|
|
|
|
|
if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
|
|
|
|
tmp[0] == '1') {
|
|
|
|
/* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
|
|
|
|
int port;
|
|
|
|
const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
|
|
|
|
const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
|
|
|
|
const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
|
|
|
|
const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
|
|
|
|
|
|
|
|
port = vncport;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(graphics) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
|
|
|
|
/* For Xen >= 3.0.3, don't generate a fixed port mapping
|
|
|
|
* because it will almost certainly be wrong ! Just leave
|
|
|
|
* it as -1 which lets caller see that the VNC server isn't
|
2012-10-11 16:31:20 +00:00
|
|
|
* present yet. Subsequent dumps of the XML will eventually
|
2011-02-21 13:40:08 +00:00
|
|
|
* find the port in XenStore once VNC server has started
|
|
|
|
*/
|
2012-01-31 17:08:09 +00:00
|
|
|
if (port == -1 && xendConfigVersion < XEND_CONFIG_VERSION_3_0_3)
|
2011-02-21 13:40:08 +00:00
|
|
|
port = 5900 + def->id;
|
|
|
|
|
|
|
|
if ((unused && STREQ(unused, "1")) || port == -1)
|
2013-04-12 08:49:38 +00:00
|
|
|
graphics->data.vnc.autoport = true;
|
2011-02-21 13:40:08 +00:00
|
|
|
graphics->data.vnc.port = port;
|
|
|
|
|
|
|
|
if (listenAddr &&
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
virDomainGraphicsListenSetAddress(graphics, 0, listenAddr, -1, true))
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(graphics->data.vnc.auth.passwd, vncPasswd) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(graphics->data.vnc.keymap, keymap) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->graphics, 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
def->graphics[0] = graphics;
|
|
|
|
def->ngraphics = 1;
|
|
|
|
graphics = NULL;
|
|
|
|
} else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
|
|
|
|
tmp[0] == '1') {
|
|
|
|
/* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
|
|
|
|
const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
|
|
|
|
const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
|
|
|
|
|
|
|
|
if (VIR_ALLOC(graphics) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(graphics->data.sdl.display, display) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(graphics->data.sdl.xauth, xauth) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->graphics, 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
def->graphics[0] = graphics;
|
|
|
|
def->ngraphics = 1;
|
|
|
|
graphics = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
error:
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainGraphicsDefFree(graphics);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/*
|
|
|
|
* xenParseSxprGraphicsNew:
|
|
|
|
* @def: the domain config
|
|
|
|
* @root: root S-expression
|
|
|
|
* @vncport: VNC port number
|
|
|
|
*
|
|
|
|
* This parses out VNC devices from the domain S-expression
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprGraphicsNew(virDomainDefPtr def,
|
|
|
|
const struct sexpr *root, int vncport)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
virDomainGraphicsDefPtr graphics = NULL;
|
|
|
|
const struct sexpr *cur, *node;
|
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
/* append network devices and framebuffer */
|
|
|
|
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
node = cur->u.s.car;
|
|
|
|
if (sexpr_lookup(node, "device/vfb")) {
|
|
|
|
/* New style graphics config for PV guests in >= 3.0.4,
|
|
|
|
* or for HVM guests in >= 3.0.5 */
|
|
|
|
if (sexpr_node(node, "device/vfb/type")) {
|
|
|
|
tmp = sexpr_node(node, "device/vfb/type");
|
|
|
|
} else if (sexpr_node(node, "device/vfb/vnc")) {
|
|
|
|
tmp = "vnc";
|
|
|
|
} else if (sexpr_node(node, "device/vfb/sdl")) {
|
|
|
|
tmp = "sdl";
|
|
|
|
} else {
|
|
|
|
tmp = "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(graphics) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown graphics type '%s'"), tmp);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
|
|
|
|
const char *display = sexpr_node(node, "device/vfb/display");
|
|
|
|
const char *xauth = sexpr_node(node, "device/vfb/xauthority");
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(graphics->data.sdl.display, display) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(graphics->data.sdl.xauth, xauth) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
} else {
|
|
|
|
int port;
|
|
|
|
const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
|
|
|
|
const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
|
|
|
|
const char *keymap = sexpr_node(node, "device/vfb/keymap");
|
|
|
|
const char *unused = sexpr_node(node, "device/vfb/vncunused");
|
|
|
|
|
|
|
|
port = vncport;
|
|
|
|
|
|
|
|
/* Didn't find port entry in xenstore */
|
|
|
|
if (port == -1) {
|
|
|
|
const char *str = sexpr_node(node, "device/vfb/vncdisplay");
|
|
|
|
int val;
|
|
|
|
if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
|
|
|
|
port = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((unused && STREQ(unused, "1")) || port == -1)
|
2013-04-12 08:49:38 +00:00
|
|
|
graphics->data.vnc.autoport = true;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (port >= 0 && port < 5900)
|
|
|
|
port += 5900;
|
|
|
|
graphics->data.vnc.port = port;
|
|
|
|
|
|
|
|
if (listenAddr &&
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
virDomainGraphicsListenSetAddress(graphics, 0, listenAddr, -1, true))
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(graphics->data.vnc.auth.passwd, vncPasswd) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(graphics->data.vnc.keymap, keymap) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->graphics, 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
def->graphics[0] = graphics;
|
|
|
|
def->ngraphics = 1;
|
|
|
|
graphics = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainGraphicsDefFree(graphics);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
2011-02-21 13:40:08 +00:00
|
|
|
/**
|
2012-01-17 08:26:13 +00:00
|
|
|
* xenParseSxprPCI:
|
|
|
|
* @def: the domain config
|
2011-02-21 13:40:08 +00:00
|
|
|
* @root: root sexpr
|
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* This parses out PCI devices from the domain sexpr
|
2011-02-21 13:40:08 +00:00
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprPCI(virDomainDefPtr def,
|
|
|
|
const struct sexpr *root)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
const struct sexpr *cur, *tmp = NULL, *node;
|
|
|
|
virDomainHostdevDefPtr dev = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* With the (domain ...) block we have the following odd setup
|
|
|
|
*
|
|
|
|
* (device
|
|
|
|
* (pci
|
|
|
|
* (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
|
|
|
|
* (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
|
|
|
|
* )
|
|
|
|
* )
|
|
|
|
*
|
|
|
|
* Normally there is one (device ...) block per device, but in
|
2011-06-24 14:01:10 +00:00
|
|
|
* weird world of Xen PCI, once (device ...) covers multiple
|
2011-02-21 13:40:08 +00:00
|
|
|
* devices.
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
node = cur->u.s.car;
|
|
|
|
if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tmp)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
const char *domain = NULL;
|
|
|
|
const char *bus = NULL;
|
|
|
|
const char *slot = NULL;
|
|
|
|
const char *func = NULL;
|
|
|
|
int domainID;
|
|
|
|
int busID;
|
|
|
|
int slotID;
|
|
|
|
int funcID;
|
|
|
|
|
|
|
|
node = cur->u.s.car;
|
|
|
|
if (!sexpr_lookup(node, "dev"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!(domain = sexpr_node(node, "dev/domain"))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing PCI domain"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!(bus = sexpr_node(node, "dev/bus"))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing PCI bus"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!(slot = sexpr_node(node, "dev/slot"))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing PCI slot"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!(func = sexpr_node(node, "dev/func"))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("missing PCI func"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse PCI domain '%s'"), domain);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse PCI bus '%s'"), bus);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse PCI slot '%s'"), slot);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse PCI func '%s'"), func);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2012-01-31 09:16:54 +00:00
|
|
|
if (!(dev = virDomainHostdevDefAlloc()))
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
|
2013-04-10 10:09:23 +00:00
|
|
|
dev->managed = false;
|
2011-02-21 13:40:08 +00:00
|
|
|
dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
|
2013-03-18 19:56:12 +00:00
|
|
|
dev->source.subsys.u.pci.addr.domain = domainID;
|
|
|
|
dev->source.subsys.u.pci.addr.bus = busID;
|
|
|
|
dev->source.subsys.u.pci.addr.slot = slotID;
|
|
|
|
dev->source.subsys.u.pci.addr.function = funcID;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
|
2012-01-31 09:16:54 +00:00
|
|
|
virDomainHostdevDefFree(dev);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def->hostdevs[def->nhostdevs++] = dev;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virDomainHostdevDefFree(dev);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2011-02-21 13:40:12 +00:00
|
|
|
* xenParseSxpr:
|
2011-02-21 13:40:08 +00:00
|
|
|
* @root: the root of the parsed S-Expression
|
|
|
|
* @xendConfigVersion: version of xend
|
|
|
|
* @cpus: set of cpus the domain may be pinned to
|
2012-01-17 08:26:13 +00:00
|
|
|
* @tty: the console pty path
|
|
|
|
* @vncport: VNC port number
|
2011-02-21 13:40:08 +00:00
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* Parse the xend S-expression description and turn it into a virDomainDefPtr
|
|
|
|
* representing these settings as closely as is practical.
|
2011-02-21 13:40:08 +00:00
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* Returns the domain config or NULL in case of error.
|
|
|
|
* The caller must free() the returned value.
|
2011-02-21 13:40:08 +00:00
|
|
|
*/
|
|
|
|
virDomainDefPtr
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxpr(const struct sexpr *root,
|
|
|
|
int xendConfigVersion,
|
|
|
|
const char *cpus, char *tty, int vncport)
|
2011-02-21 13:40:08 +00:00
|
|
|
{
|
|
|
|
const char *tmp;
|
|
|
|
virDomainDefPtr def;
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
int hvm = 0, vmlocaltime;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
tmp = sexpr_node(root, "domain/domid");
|
2012-01-31 17:08:09 +00:00
|
|
|
if (tmp == NULL && xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { /* domid was mandatory */
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, missing id"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
def->virtType = VIR_DOMAIN_VIRT_XEN;
|
|
|
|
if (tmp)
|
|
|
|
def->id = sexpr_int(root, "domain/domid");
|
|
|
|
else
|
|
|
|
def->id = -1;
|
|
|
|
|
|
|
|
if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
if (def->name == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, missing name"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp = sexpr_node(root, "domain/uuid");
|
|
|
|
if (tmp == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("domain information incomplete, missing name"));
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-10-12 23:24:52 +00:00
|
|
|
if (virUUIDParse(tmp, def->uuid) < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (sexpr_node_copy(root, "domain/description", &def->description) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
|
|
|
|
if (!hvm) {
|
|
|
|
if (sexpr_node_copy(root, "domain/bootloader",
|
|
|
|
&def->os.bootloader) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (!def->os.bootloader &&
|
|
|
|
sexpr_has(root, "domain/bootloader") &&
|
2013-05-03 12:51:56 +00:00
|
|
|
VIR_STRDUP(def->os.bootloader, "") < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (def->os.bootloader &&
|
|
|
|
sexpr_node_copy(root, "domain/bootloader_args",
|
|
|
|
&def->os.bootloaderArgs) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(def->os.type, hvm ? "hvm" : "linux") < 0)
|
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (def->id != 0) {
|
|
|
|
if (sexpr_lookup(root, "domain/image")) {
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenParseSxprOS(root, def, hvm) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-02 20:27:39 +00:00
|
|
|
def->mem.max_balloon = (sexpr_u64(root, "domain/maxmem") << 10);
|
|
|
|
def->mem.cur_balloon = (sexpr_u64(root, "domain/memory") << 10);
|
2011-02-21 13:40:08 +00:00
|
|
|
if (def->mem.cur_balloon > def->mem.max_balloon)
|
|
|
|
def->mem.cur_balloon = def->mem.max_balloon;
|
|
|
|
|
|
|
|
if (cpus != NULL) {
|
2012-09-14 07:47:01 +00:00
|
|
|
if (virBitmapParse(cpus, 0, &def->cpumask,
|
|
|
|
VIR_DOMAIN_CPUMASK_LEN) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid CPU mask %s"), cpus);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def->maxvcpus = sexpr_int(root, "domain/vcpus");
|
|
|
|
def->vcpus = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
|
|
|
|
if (!def->vcpus || def->maxvcpus < def->vcpus)
|
|
|
|
def->vcpus = def->maxvcpus;
|
|
|
|
|
|
|
|
tmp = sexpr_node(root, "domain/on_poweroff");
|
|
|
|
if (tmp != NULL) {
|
|
|
|
if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown lifecycle type %s"), tmp);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
|
|
|
|
|
|
|
|
tmp = sexpr_node(root, "domain/on_reboot");
|
|
|
|
if (tmp != NULL) {
|
|
|
|
if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown lifecycle type %s"), tmp);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
|
|
|
|
|
|
|
|
tmp = sexpr_node(root, "domain/on_crash");
|
|
|
|
if (tmp != NULL) {
|
|
|
|
if ((def->onCrash = virDomainLifecycleCrashTypeFromString(tmp)) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown lifecycle type %s"), tmp);
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
|
|
|
|
|
|
|
|
if (hvm) {
|
|
|
|
if (sexpr_int(root, "domain/image/hvm/acpi"))
|
|
|
|
def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
|
|
|
|
if (sexpr_int(root, "domain/image/hvm/apic"))
|
|
|
|
def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
|
|
|
|
if (sexpr_int(root, "domain/image/hvm/pae"))
|
|
|
|
def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
|
|
|
|
if (sexpr_int(root, "domain/image/hvm/hap"))
|
|
|
|
def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
|
2011-06-15 13:27:43 +00:00
|
|
|
if (sexpr_int(root, "domain/image/hvm/viridian"))
|
|
|
|
def->features |= (1 << VIR_DOMAIN_FEATURE_VIRIDIAN);
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
}
|
2011-02-21 13:40:08 +00:00
|
|
|
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
/* 12aaf4a2486b (3.0.3) added a second low-priority 'localtime' setting */
|
|
|
|
vmlocaltime = sexpr_int(root, "domain/localtime");
|
|
|
|
if (hvm) {
|
|
|
|
const char *value = sexpr_node(root, "domain/image/hvm/localtime");
|
|
|
|
if (value) {
|
|
|
|
if (virStrToLong_i(value, NULL, 0, &vmlocaltime) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown localtime offset %s"), value);
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* only managed HVM domains since 3.1.0 have persistent rtc_timeoffset */
|
|
|
|
if (xendConfigVersion < XEND_CONFIG_VERSION_3_1_0) {
|
|
|
|
if (vmlocaltime)
|
|
|
|
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
|
|
|
|
else
|
|
|
|
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
|
|
|
|
def->clock.data.utc_reset = true;
|
|
|
|
} else {
|
|
|
|
int rtc_offset;
|
|
|
|
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_VARIABLE;
|
|
|
|
rtc_offset = sexpr_int(root, "domain/image/hvm/rtc_timeoffset");
|
|
|
|
def->clock.data.variable.adjustment = rtc_offset;
|
|
|
|
def->clock.data.variable.basis = vmlocaltime ?
|
|
|
|
VIR_DOMAIN_CLOCK_BASIS_LOCALTIME :
|
|
|
|
VIR_DOMAIN_CLOCK_BASIS_UTC;
|
|
|
|
}
|
2011-05-10 11:24:14 +00:00
|
|
|
|
|
|
|
if (sexpr_lookup(root, "domain/image/hvm/hpet")) {
|
|
|
|
virDomainTimerDefPtr timer;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->clock.timers, 1) < 0 ||
|
2013-07-04 10:19:27 +00:00
|
|
|
VIR_ALLOC(timer) < 0)
|
2011-05-10 11:24:14 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
timer->name = VIR_DOMAIN_TIMER_NAME_HPET;
|
|
|
|
timer->present = sexpr_int(root, "domain/image/hvm/hpet");
|
|
|
|
timer->tickpolicy = -1;
|
|
|
|
|
|
|
|
def->clock.ntimers = 1;
|
|
|
|
def->clock.timers[0] = timer;
|
|
|
|
}
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
} else {
|
|
|
|
const char *value = sexpr_node(root, "domain/image/linux/localtime");
|
|
|
|
if (value) {
|
|
|
|
if (virStrToLong_i(value, NULL, 0, &vmlocaltime) < 0) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown localtime offset %s"), value);
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* PV domains do not have an emulated RTC and the offset is fixed. */
|
|
|
|
if (vmlocaltime)
|
2011-09-05 06:22:36 +00:00
|
|
|
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
else
|
|
|
|
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
|
|
|
|
def->clock.data.utc_reset = true;
|
|
|
|
} /* !hvm */
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (sexpr_node_copy(root, hvm ?
|
|
|
|
"domain/image/hvm/device_model" :
|
|
|
|
"domain/image/linux/device_model",
|
|
|
|
&def->emulator) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
/* append block devices */
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenParseSxprDisks(def, root, hvm, xendConfigVersion) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenParseSxprNets(def, root) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenParseSxprPCI(def, root) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* New style graphics device config */
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenParseSxprGraphicsNew(def, root, vncport) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
|
|
|
|
if ((def->ngraphics == 0) &&
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprGraphicsOld(def, root, hvm, xendConfigVersion,
|
2011-02-21 13:40:08 +00:00
|
|
|
vncport) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
|
|
/* Old style cdrom config from Xen <= 3.0.2 */
|
|
|
|
if (hvm &&
|
2012-01-31 17:08:09 +00:00
|
|
|
xendConfigVersion == XEND_CONFIG_VERSION_3_0_2) {
|
2011-02-21 13:40:08 +00:00
|
|
|
tmp = sexpr_node(root, "domain/image/hvm/cdrom");
|
|
|
|
if ((tmp != NULL) && (tmp[0] != 0)) {
|
|
|
|
virDomainDiskDefPtr disk;
|
|
|
|
if (VIR_ALLOC(disk) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->src, tmp) < 0) {
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->dst, "hdc") < 0) {
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->driverName, "file") < 0) {
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
2013-04-10 11:23:56 +00:00
|
|
|
disk->readonly = true;
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
|
|
|
|
virDomainDiskDefFree(disk);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
def->disks[def->ndisks++] = disk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Floppy disk config */
|
|
|
|
if (hvm) {
|
|
|
|
const char *const fds[] = { "fda", "fdb" };
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < ARRAY_CARDINALITY(fds); i++) {
|
2011-02-21 13:40:08 +00:00
|
|
|
tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
|
|
|
|
if ((tmp != NULL) && (tmp[0] != 0)) {
|
|
|
|
virDomainDiskDefPtr disk;
|
|
|
|
if (VIR_ALLOC(disk) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->src, tmp) < 0) {
|
2011-02-21 13:40:08 +00:00
|
|
|
VIR_FREE(disk);
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->dst, fds[i]) < 0) {
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
2013-05-03 12:51:56 +00:00
|
|
|
if (VIR_STRDUP(disk->driverName, "file") < 0) {
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainDiskDefFree(disk);
|
2013-05-03 12:51:56 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
|
|
|
|
virDomainDiskDefFree(disk);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
def->disks[def->ndisks++] = disk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* in case of HVM we have USB device emulation */
|
|
|
|
if (hvm &&
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprUSB(def, root) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* Character device config */
|
|
|
|
if (hvm) {
|
2011-02-25 14:41:12 +00:00
|
|
|
const struct sexpr *serial_root;
|
|
|
|
bool have_multiple_serials = false;
|
|
|
|
|
|
|
|
serial_root = sexpr_lookup(root, "domain/image/hvm/serial");
|
|
|
|
if (serial_root) {
|
|
|
|
const struct sexpr *cur, *node, *cur2;
|
|
|
|
int ports_skipped = 0;
|
|
|
|
|
|
|
|
for (cur = serial_root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
|
|
|
|
node = cur->u.s.car;
|
|
|
|
|
|
|
|
for (cur2 = node; cur2->kind == SEXPR_CONS; cur2 = cur2->u.s.cdr) {
|
|
|
|
tmp = cur2->u.s.car->u.value;
|
|
|
|
|
|
|
|
if (tmp && STRNEQ(tmp, "none")) {
|
|
|
|
virDomainChrDefPtr chr;
|
|
|
|
if ((chr = xenParseSxprChar(tmp, tty)) == NULL)
|
|
|
|
goto error;
|
|
|
|
if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
|
|
|
|
virDomainChrDefFree(chr);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-25 14:41:12 +00:00
|
|
|
}
|
|
|
|
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
|
|
|
|
chr->target.port = def->nserials + ports_skipped;
|
|
|
|
def->serials[def->nserials++] = chr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ports_skipped++;
|
|
|
|
|
|
|
|
have_multiple_serials = true;
|
|
|
|
}
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
2011-02-25 14:41:12 +00:00
|
|
|
|
|
|
|
if (!have_multiple_serials) {
|
|
|
|
tmp = sexpr_node(root, "domain/image/hvm/serial");
|
|
|
|
if (tmp && STRNEQ(tmp, "none")) {
|
|
|
|
virDomainChrDefPtr chr;
|
|
|
|
if ((chr = xenParseSxprChar(tmp, tty)) == NULL)
|
|
|
|
goto error;
|
|
|
|
if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
|
|
|
|
virDomainChrDefFree(chr);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-25 14:41:12 +00:00
|
|
|
}
|
|
|
|
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
|
2011-04-14 16:05:14 +00:00
|
|
|
chr->target.port = 0;
|
2011-02-25 14:41:12 +00:00
|
|
|
def->serials[def->nserials++] = chr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-21 13:40:08 +00:00
|
|
|
tmp = sexpr_node(root, "domain/image/hvm/parallel");
|
|
|
|
if (tmp && STRNEQ(tmp, "none")) {
|
|
|
|
virDomainChrDefPtr chr;
|
|
|
|
/* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
|
2011-02-21 13:40:12 +00:00
|
|
|
if ((chr = xenParseSxprChar(tmp, NULL)) == NULL)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
|
|
|
|
virDomainChrDefFree(chr);
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
|
2011-04-14 16:05:14 +00:00
|
|
|
chr->target.port = 0;
|
2011-02-21 13:40:08 +00:00
|
|
|
def->parallels[def->nparallels++] = chr;
|
|
|
|
}
|
2012-01-29 19:10:00 +00:00
|
|
|
} else if (def->id != 0) {
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
def->nconsoles = 1;
|
|
|
|
if (VIR_ALLOC_N(def->consoles, 1) < 0)
|
2013-07-04 10:19:27 +00:00
|
|
|
goto error;
|
2011-02-21 13:40:08 +00:00
|
|
|
/* Fake a paravirt console, since that's not in the sexpr */
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
if (!(def->consoles[0] = xenParseSxprChar("pty", tty)))
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
|
|
|
def->consoles[0]->target.port = 0;
|
|
|
|
def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
|
2011-02-21 13:40:08 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(tty);
|
|
|
|
|
|
|
|
|
|
|
|
/* Sound device config */
|
|
|
|
if (hvm &&
|
|
|
|
(tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
|
|
|
|
*tmp) {
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenParseSxprSound(def, tmp) < 0)
|
2011-02-21 13:40:08 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(tty);
|
|
|
|
virDomainDefFree(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenParseSxprString:
|
|
|
|
* @sexpr: the root of the parsed S-Expression
|
|
|
|
* @xendConfigVersion: version of xend
|
|
|
|
* @tty: the console pty path
|
|
|
|
* @vncport: VNC port number
|
|
|
|
*
|
|
|
|
* Parse the xend S-expression description and turn it into a virDomainDefPtr
|
|
|
|
* representing these settings as closely as is practical.
|
|
|
|
*
|
|
|
|
* Returns the domain config or NULL in case of error.
|
|
|
|
* The caller must free() the returned value.
|
|
|
|
*/
|
2011-02-21 13:40:08 +00:00
|
|
|
virDomainDefPtr
|
2011-02-21 13:40:12 +00:00
|
|
|
xenParseSxprString(const char *sexpr,
|
2011-02-21 13:40:08 +00:00
|
|
|
int xendConfigVersion, char *tty, int vncport)
|
|
|
|
{
|
|
|
|
struct sexpr *root = string2sexpr(sexpr);
|
|
|
|
virDomainDefPtr def;
|
|
|
|
|
|
|
|
if (!root)
|
|
|
|
return NULL;
|
|
|
|
|
2011-02-21 13:40:12 +00:00
|
|
|
def = xenParseSxpr(root, xendConfigVersion, NULL, tty, vncport);
|
2011-02-21 13:40:08 +00:00
|
|
|
|
|
|
|
sexpr_free(root);
|
|
|
|
|
|
|
|
return def;
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Converter functions to go from the XML tree to an S-Expr for Xen *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2012-01-17 08:26:13 +00:00
|
|
|
* xenFormatSxprGraphicsNew:
|
|
|
|
* @def: the domain config
|
|
|
|
* @buf: a buffer for the result S-expression
|
2011-02-21 13:40:09 +00:00
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* Convert the graphics part of the domain description into a S-expression
|
|
|
|
* in buf. (HVM > 3.0.4 or PV > 3.0.3)
|
2011-02-21 13:40:09 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error
|
|
|
|
*/
|
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprGraphicsNew(virDomainGraphicsDefPtr def,
|
|
|
|
virBufferPtr buf)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
const char *listenAddr;
|
|
|
|
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
|
|
|
|
def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected graphics type %d"),
|
|
|
|
def->type);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "(device (vkbd))");
|
|
|
|
virBufferAddLit(buf, "(device (vfb ");
|
|
|
|
|
|
|
|
if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
|
|
|
|
virBufferAddLit(buf, "(type sdl)");
|
|
|
|
if (def->data.sdl.display)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(display '%s')", def->data.sdl.display);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.sdl.xauth)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
|
2011-02-21 13:40:09 +00:00
|
|
|
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
|
|
|
|
virBufferAddLit(buf, "(type vnc)");
|
|
|
|
if (def->data.vnc.autoport) {
|
|
|
|
virBufferAddLit(buf, "(vncunused 1)");
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(buf, "(vncunused 0)");
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
listenAddr = virDomainGraphicsListenGetAddress(def, 0);
|
|
|
|
if (listenAddr)
|
|
|
|
virBufferAsprintf(buf, "(vnclisten '%s')", listenAddr);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.vnc.auth.passwd)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.vnc.keymap)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "))");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/**
|
|
|
|
* xenFormatSxprGraphicsOld:
|
|
|
|
* @def: the domain config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
* @xendConfigVersion: version of xend
|
|
|
|
*
|
|
|
|
* Convert the graphics part of the domain description into a S-expression
|
|
|
|
* in buf. (HVM <= 3.0.4 or PV <= 3.0.3)
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprGraphicsOld(virDomainGraphicsDefPtr def,
|
|
|
|
virBufferPtr buf,
|
|
|
|
int xendConfigVersion)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
const char *listenAddr;
|
|
|
|
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->type != VIR_DOMAIN_GRAPHICS_TYPE_SDL &&
|
|
|
|
def->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected graphics type %d"),
|
|
|
|
def->type);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
|
|
|
|
virBufferAddLit(buf, "(sdl 1)");
|
|
|
|
if (def->data.sdl.display)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(display '%s')", def->data.sdl.display);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.sdl.xauth)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(xauthority '%s')", def->data.sdl.xauth);
|
2011-02-21 13:40:09 +00:00
|
|
|
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
|
|
|
|
virBufferAddLit(buf, "(vnc 1)");
|
2012-01-31 17:08:09 +00:00
|
|
|
if (xendConfigVersion >= XEND_CONFIG_VERSION_3_0_3) {
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.vnc.autoport) {
|
|
|
|
virBufferAddLit(buf, "(vncunused 1)");
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(buf, "(vncunused 0)");
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(vncdisplay %d)", def->data.vnc.port-5900);
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
conf: add <listen> subelement to domain <graphics> element
Once it's plugged in, the <listen> element will be an optional
replacement for the "listen" attribute that graphics elements already
have. If the <listen> element is type='address', it will have an
attribute called 'address' which will contain an IP address or dns
name that the guest's display server should listen on. If, however,
type='network', the <listen> element should have an attribute called
'network' that will be set to the name of a network configuration to
get the IP address from.
* docs/schemas/domain.rng: updated to allow the <listen> element
* docs/formatdomain.html.in: document the <listen> element and its
attributes.
* src/conf/domain_conf.[hc]:
1) The domain parser, formatter, and data structure are modified to
support 0 or more <listen> subelements to each <graphics>
element. The old style "legacy" listen attribute is also still
accepted, and will be stored internally just as if it were a
separate <listen> element. On output (i.e. format), the address
attribute of the first <listen> element of type 'address' will be
duplicated in the legacy "listen" attribute of the <graphic>
element.
2) The "listenAddr" attribute has been removed from the unions in
virDomainGRaphicsDef for graphics types vnc, rdp, and spice.
This attribute is now in the <listen> subelement (aka
virDomainGraphicsListenDef)
3) Helper functions were written to provide simple access
(both Get and Set) to the listen elements and their attributes.
* src/libvirt_private.syms: export the listen helper functions
* src/qemu/qemu_command.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/vbox/vbox_tmpl.c,
src/vmx/vmx.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c
Modify all these files to use the listen helper functions rather
than directly referencing the (now missing) listenAddr
attribute. There can be multiple <listen> elements to a single
<graphics>, but the drivers all currently only support one, so all
replacements of direct access with a helper function indicate index
"0".
* tests/* - only 3 of these are new files added explicitly to test the
new <listen> element. All the others have been modified to reflect
the fact that any legacy "listen" attributes passed in to the domain
parse will be saved in a <listen> element (i.e. one of the
virDomainGraphicsListenDefs), and during the domain format function,
both the <listen> element as well as the legacy attributes will be
output.
2011-07-07 04:20:28 +00:00
|
|
|
listenAddr = virDomainGraphicsListenGetAddress(def, 0);
|
|
|
|
if (listenAddr)
|
|
|
|
virBufferAsprintf(buf, "(vnclisten '%s')", listenAddr);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.vnc.auth.passwd)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.vnc.keymap)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(keymap '%s')", def->data.vnc.keymap);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenFormatSxprChr:
|
|
|
|
* @def: the domain config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
*
|
|
|
|
* Convert the character device part of the domain config into a S-expression
|
|
|
|
* in buf.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprChr(virDomainChrDefPtr def,
|
|
|
|
virBufferPtr buf)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
const char *type = virDomainChrTypeToString(def->source.type);
|
|
|
|
|
|
|
|
if (!type) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("unexpected chr device type"));
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (def->source.type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_NULL:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_VC:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
2011-04-14 19:27:47 +00:00
|
|
|
virBufferAdd(buf, type, -1);
|
2011-02-21 13:40:09 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "%s:", type);
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
virBufferEscapeSexpr(buf, "%s", def->source.data.file.path);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_TCP:
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "%s:%s:%s%s",
|
2011-02-21 13:40:09 +00:00
|
|
|
(def->source.data.tcp.protocol
|
|
|
|
== VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW ?
|
|
|
|
"tcp" : "telnet"),
|
|
|
|
(def->source.data.tcp.host ?
|
|
|
|
def->source.data.tcp.host : ""),
|
|
|
|
(def->source.data.tcp.service ?
|
|
|
|
def->source.data.tcp.service : ""),
|
|
|
|
(def->source.data.tcp.listen ?
|
|
|
|
",server,nowait" : ""));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UDP:
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "%s:%s:%s@%s:%s", type,
|
2011-02-21 13:40:09 +00:00
|
|
|
(def->source.data.udp.connectHost ?
|
|
|
|
def->source.data.udp.connectHost : ""),
|
|
|
|
(def->source.data.udp.connectService ?
|
|
|
|
def->source.data.udp.connectService : ""),
|
|
|
|
(def->source.data.udp.bindHost ?
|
|
|
|
def->source.data.udp.bindHost : ""),
|
|
|
|
(def->source.data.udp.bindService ?
|
|
|
|
def->source.data.udp.bindService : ""));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "%s:", type);
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(buf, "%s", def->source.data.nix.path);
|
|
|
|
if (def->source.data.nix.listen)
|
|
|
|
virBufferAddLit(buf, ",server,nowait");
|
|
|
|
break;
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
|
|
|
|
default:
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported chr device type '%s'"), type);
|
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and
QEMU both support multiple paravirt consoles. The LXC
driver can also be trivially made to support multiple
consoles. This patch extends the XML to allow multiple
<console> elements in the XML. It also makes the UML
and QEMU drivers support this config.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Allow
multiple <console> devices
* src/lxc/lxc_driver.c, src/xen/xen_driver.c,
src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for
internal API changes
* src/security/security_selinux.c, src/security/virt-aa-helper.c:
Only label consoles that aren't a copy of the serial device
* src/qemu/qemu_command.c, src/qemu/qemu_driver.c,
src/qemu/qemu_process.c, src/uml/uml_conf.c,
src/uml/uml_driver.c: Support multiple console devices
* tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra
tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV
for all console /channel tests
* tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args,
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args
tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update
for correct chardev syntax
* tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args,
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New
test file
2011-02-23 18:27:23 +00:00
|
|
|
return -1;
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virBufferError(buf)) {
|
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2012-01-17 08:26:13 +00:00
|
|
|
* xenFormatSxprDisk:
|
|
|
|
* @node: node containing the disk description
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
* @hvm: true or 1 if domain is HVM
|
2011-02-21 13:40:09 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2012-01-17 08:26:13 +00:00
|
|
|
* @isAttach: create expression for device attach (1).
|
2011-02-21 13:40:09 +00:00
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* Convert the disk device part of the domain config into a S-expresssion in buf.
|
2011-02-21 13:40:09 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2011-07-08 21:58:28 +00:00
|
|
|
xenFormatSxprDisk(virDomainDiskDefPtr def,
|
2011-02-21 13:40:12 +00:00
|
|
|
virBufferPtr buf,
|
|
|
|
int hvm,
|
|
|
|
int xendConfigVersion,
|
|
|
|
int isAttach)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
/* Xend (all versions) put the floppy device config
|
|
|
|
* under the hvm (image (os)) block
|
|
|
|
*/
|
|
|
|
if (hvm &&
|
|
|
|
def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
|
|
|
if (isAttach) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Cannot directly attach floppy %s"), def->src);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Xend <= 3.0.2 doesn't include cdrom config here */
|
|
|
|
if (hvm &&
|
|
|
|
def->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
|
2012-01-31 17:08:09 +00:00
|
|
|
xendConfigVersion == XEND_CONFIG_VERSION_3_0_2) {
|
2011-02-21 13:40:09 +00:00
|
|
|
if (isAttach) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Cannot directly attach CDROM %s"), def->src);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isAttach)
|
|
|
|
virBufferAddLit(buf, "(device ");
|
|
|
|
|
|
|
|
/* Normally disks are in a (device (vbd ...)) block
|
|
|
|
* but blktap disks ended up in a differently named
|
|
|
|
* (device (tap ....)) block.... */
|
|
|
|
if (def->driverName && STREQ(def->driverName, "tap")) {
|
|
|
|
virBufferAddLit(buf, "(tap ");
|
|
|
|
} else if (def->driverName && STREQ(def->driverName, "tap2")) {
|
|
|
|
virBufferAddLit(buf, "(tap2 ");
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(buf, "(vbd ");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hvm) {
|
|
|
|
/* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
|
2012-01-31 17:08:09 +00:00
|
|
|
if (xendConfigVersion == XEND_CONFIG_VERSION_3_0_2) {
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(buf, "(dev 'ioemu:%s')", def->dst);
|
|
|
|
} else {
|
|
|
|
/* But newer does not */
|
|
|
|
virBufferEscapeSexpr(buf, "(dev '%s:", def->dst);
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "%s')",
|
2011-02-21 13:40:09 +00:00
|
|
|
def->device == VIR_DOMAIN_DISK_DEVICE_CDROM ?
|
|
|
|
"cdrom" : "disk");
|
|
|
|
}
|
|
|
|
} else if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
|
|
|
virBufferEscapeSexpr(buf, "(dev '%s:cdrom')", def->dst);
|
|
|
|
} else {
|
|
|
|
virBufferEscapeSexpr(buf, "(dev '%s')", def->dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->src) {
|
|
|
|
if (def->driverName) {
|
|
|
|
if (STREQ(def->driverName, "tap") ||
|
|
|
|
STREQ(def->driverName, "tap2")) {
|
2012-10-15 21:47:42 +00:00
|
|
|
const char *type;
|
|
|
|
|
|
|
|
if (!def->format || def->format == VIR_STORAGE_FILE_RAW)
|
2012-09-28 23:48:58 +00:00
|
|
|
type = "aio";
|
2012-10-15 21:47:42 +00:00
|
|
|
else
|
|
|
|
type = virStorageFileFormatTypeToString(def->format);
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
|
2012-09-28 23:48:58 +00:00
|
|
|
virBufferEscapeSexpr(buf, "%s:", type);
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(buf, "%s')", def->src);
|
|
|
|
} else {
|
|
|
|
virBufferEscapeSexpr(buf, "(uname '%s:", def->driverName);
|
|
|
|
virBufferEscapeSexpr(buf, "%s')", def->src);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
|
|
|
|
virBufferEscapeSexpr(buf, "(uname 'file:%s')", def->src);
|
|
|
|
} else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
|
|
|
|
if (def->src[0] == '/')
|
|
|
|
virBufferEscapeSexpr(buf, "(uname 'phy:%s')", def->src);
|
|
|
|
else
|
|
|
|
virBufferEscapeSexpr(buf, "(uname 'phy:/dev/%s')",
|
|
|
|
def->src);
|
|
|
|
} else {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported disk type %s"),
|
|
|
|
virDomainDiskTypeToString(def->type));
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->readonly)
|
|
|
|
virBufferAddLit(buf, "(mode 'r')");
|
|
|
|
else if (def->shared)
|
|
|
|
virBufferAddLit(buf, "(mode 'w!')");
|
|
|
|
else
|
|
|
|
virBufferAddLit(buf, "(mode 'w')");
|
2011-08-13 21:42:48 +00:00
|
|
|
if (def->transient) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2012-07-18 13:17:20 +00:00
|
|
|
_("transient disks not supported yet"));
|
2011-08-13 21:42:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (!isAttach)
|
|
|
|
virBufferAddLit(buf, ")");
|
|
|
|
|
|
|
|
virBufferAddLit(buf, ")");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-01-17 08:26:13 +00:00
|
|
|
* xenFormatSxprNet:
|
|
|
|
* @conn: connection
|
|
|
|
* @def: the domain config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
* @hvm: true or 1 if domain is HVM
|
2011-02-21 13:40:09 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2012-01-17 08:26:13 +00:00
|
|
|
* @isAttach: create expression for device attach (1).
|
2011-02-21 13:40:09 +00:00
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* Convert the interface description of the domain config into a S-expression in buf.
|
2011-02-21 13:40:09 +00:00
|
|
|
* This is a temporary interface as the S-Expr interface
|
|
|
|
* will be replaced by XML-RPC in the future. However the XML format should
|
|
|
|
* stay valid over time.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprNet(virConnectPtr conn,
|
|
|
|
virDomainNetDefPtr def,
|
|
|
|
virBufferPtr buf,
|
|
|
|
int hvm,
|
|
|
|
int xendConfigVersion,
|
|
|
|
int isAttach)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
const char *script = DEFAULT_VIF_SCRIPT;
|
2013-03-26 11:21:33 +00:00
|
|
|
char macaddr[VIR_MAC_STRING_BUFLEN];
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
def->type != VIR_DOMAIN_NET_TYPE_NETWORK &&
|
|
|
|
def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unsupported network type %d"), def->type);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
config: report error when script given for inappropriate interface type
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=638633
Although scripts are not used by interfaces of type other than
"ethernet" in qemu, due to the fact that the parser stores the script
name in a union that is only valid when type is ethernet or bridge,
there is no way for anyone except the parser itself to catch the
problem of specifying an interface script for an inappropriate
interface type (by the time the parsed data gets back to the code that
called the parser, all evidence that a script was specified is
forgotten).
Since the parser itself should be agnostic to which type of interface
allows scripts (an example of why: a script specified for an interface
of type bridge is valid for xen domains, but not for qemu domains),
the solution here is to move the script out of the union(s) in the
DomainNetDef, always populate it when specified (regardless of
interface type), and let the driver decide whether or not it is
appropriate.
Currently the qemu, xen, libxml, and uml drivers recognize the script
parameter and do something with it (the uml driver only to report that
it isn't supported). Those drivers have been updated to log a
CONFIG_UNSUPPORTED error when a script is specified for an interface
type that's inappropriate for that particular hypervisor.
(NB: There was earlier discussion of solving this problem by adding a
VALIDATE flag to all libvirt APIs that accept XML, which would cause
the XML to be validated against the RNG files. One statement during
that discussion was that the RNG shouldn't contain hypervisor-specific
things, though, and a proper solution to this problem would require
that (again, because a script for an interface of type "bridge" is
accepted by xen, but not by qemu).
2012-01-06 17:59:47 +00:00
|
|
|
if (def->script &&
|
|
|
|
def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
def->type != VIR_DOMAIN_NET_TYPE_ETHERNET) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("scripts are not supported on interfaces of type %s"),
|
|
|
|
virDomainNetTypeToString(def->type));
|
config: report error when script given for inappropriate interface type
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=638633
Although scripts are not used by interfaces of type other than
"ethernet" in qemu, due to the fact that the parser stores the script
name in a union that is only valid when type is ethernet or bridge,
there is no way for anyone except the parser itself to catch the
problem of specifying an interface script for an inappropriate
interface type (by the time the parsed data gets back to the code that
called the parser, all evidence that a script was specified is
forgotten).
Since the parser itself should be agnostic to which type of interface
allows scripts (an example of why: a script specified for an interface
of type bridge is valid for xen domains, but not for qemu domains),
the solution here is to move the script out of the union(s) in the
DomainNetDef, always populate it when specified (regardless of
interface type), and let the driver decide whether or not it is
appropriate.
Currently the qemu, xen, libxml, and uml drivers recognize the script
parameter and do something with it (the uml driver only to report that
it isn't supported). Those drivers have been updated to log a
CONFIG_UNSUPPORTED error when a script is specified for an interface
type that's inappropriate for that particular hypervisor.
(NB: There was earlier discussion of solving this problem by adding a
VALIDATE flag to all libvirt APIs that accept XML, which would cause
the XML to be validated against the RNG files. One statement during
that discussion was that the RNG shouldn't contain hypervisor-specific
things, though, and a proper solution to this problem would require
that (again, because a script for an interface of type "bridge" is
accepted by xen, but not by qemu).
2012-01-06 17:59:47 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (!isAttach)
|
|
|
|
virBufferAddLit(buf, "(device ");
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "(vif ");
|
|
|
|
|
2013-03-26 11:21:33 +00:00
|
|
|
virBufferAsprintf(buf, "(mac '%s')", virMacAddrFormat(&def->mac, macaddr));
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
switch (def->type) {
|
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
|
|
|
virBufferEscapeSexpr(buf, "(bridge '%s')", def->data.bridge.brname);
|
config: report error when script given for inappropriate interface type
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=638633
Although scripts are not used by interfaces of type other than
"ethernet" in qemu, due to the fact that the parser stores the script
name in a union that is only valid when type is ethernet or bridge,
there is no way for anyone except the parser itself to catch the
problem of specifying an interface script for an inappropriate
interface type (by the time the parsed data gets back to the code that
called the parser, all evidence that a script was specified is
forgotten).
Since the parser itself should be agnostic to which type of interface
allows scripts (an example of why: a script specified for an interface
of type bridge is valid for xen domains, but not for qemu domains),
the solution here is to move the script out of the union(s) in the
DomainNetDef, always populate it when specified (regardless of
interface type), and let the driver decide whether or not it is
appropriate.
Currently the qemu, xen, libxml, and uml drivers recognize the script
parameter and do something with it (the uml driver only to report that
it isn't supported). Those drivers have been updated to log a
CONFIG_UNSUPPORTED error when a script is specified for an interface
type that's inappropriate for that particular hypervisor.
(NB: There was earlier discussion of solving this problem by adding a
VALIDATE flag to all libvirt APIs that accept XML, which would cause
the XML to be validated against the RNG files. One statement during
that discussion was that the RNG shouldn't contain hypervisor-specific
things, though, and a proper solution to this problem would require
that (again, because a script for an interface of type "bridge" is
accepted by xen, but not by qemu).
2012-01-06 17:59:47 +00:00
|
|
|
if (def->script)
|
|
|
|
script = def->script;
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
virBufferEscapeSexpr(buf, "(script '%s')", script);
|
|
|
|
if (def->data.bridge.ipaddr != NULL)
|
|
|
|
virBufferEscapeSexpr(buf, "(ip '%s')", def->data.bridge.ipaddr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
|
|
|
{
|
|
|
|
virNetworkPtr network =
|
|
|
|
virNetworkLookupByName(conn, def->data.network.name);
|
|
|
|
char *bridge;
|
|
|
|
|
|
|
|
if (!network) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_NO_NETWORK, "%s",
|
|
|
|
def->data.network.name);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bridge = virNetworkGetBridgeName(network);
|
|
|
|
virNetworkFree(network);
|
|
|
|
if (!bridge) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("network %s is not active"),
|
|
|
|
def->data.network.name);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
virBufferEscapeSexpr(buf, "(bridge '%s')", bridge);
|
|
|
|
virBufferEscapeSexpr(buf, "(script '%s')", script);
|
|
|
|
VIR_FREE(bridge);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
config: report error when script given for inappropriate interface type
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=638633
Although scripts are not used by interfaces of type other than
"ethernet" in qemu, due to the fact that the parser stores the script
name in a union that is only valid when type is ethernet or bridge,
there is no way for anyone except the parser itself to catch the
problem of specifying an interface script for an inappropriate
interface type (by the time the parsed data gets back to the code that
called the parser, all evidence that a script was specified is
forgotten).
Since the parser itself should be agnostic to which type of interface
allows scripts (an example of why: a script specified for an interface
of type bridge is valid for xen domains, but not for qemu domains),
the solution here is to move the script out of the union(s) in the
DomainNetDef, always populate it when specified (regardless of
interface type), and let the driver decide whether or not it is
appropriate.
Currently the qemu, xen, libxml, and uml drivers recognize the script
parameter and do something with it (the uml driver only to report that
it isn't supported). Those drivers have been updated to log a
CONFIG_UNSUPPORTED error when a script is specified for an interface
type that's inappropriate for that particular hypervisor.
(NB: There was earlier discussion of solving this problem by adding a
VALIDATE flag to all libvirt APIs that accept XML, which would cause
the XML to be validated against the RNG files. One statement during
that discussion was that the RNG shouldn't contain hypervisor-specific
things, though, and a proper solution to this problem would require
that (again, because a script for an interface of type "bridge" is
accepted by xen, but not by qemu).
2012-01-06 17:59:47 +00:00
|
|
|
if (def->script)
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(buf, "(script '%s')",
|
config: report error when script given for inappropriate interface type
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=638633
Although scripts are not used by interfaces of type other than
"ethernet" in qemu, due to the fact that the parser stores the script
name in a union that is only valid when type is ethernet or bridge,
there is no way for anyone except the parser itself to catch the
problem of specifying an interface script for an inappropriate
interface type (by the time the parsed data gets back to the code that
called the parser, all evidence that a script was specified is
forgotten).
Since the parser itself should be agnostic to which type of interface
allows scripts (an example of why: a script specified for an interface
of type bridge is valid for xen domains, but not for qemu domains),
the solution here is to move the script out of the union(s) in the
DomainNetDef, always populate it when specified (regardless of
interface type), and let the driver decide whether or not it is
appropriate.
Currently the qemu, xen, libxml, and uml drivers recognize the script
parameter and do something with it (the uml driver only to report that
it isn't supported). Those drivers have been updated to log a
CONFIG_UNSUPPORTED error when a script is specified for an interface
type that's inappropriate for that particular hypervisor.
(NB: There was earlier discussion of solving this problem by adding a
VALIDATE flag to all libvirt APIs that accept XML, which would cause
the XML to be validated against the RNG files. One statement during
that discussion was that the RNG shouldn't contain hypervisor-specific
things, though, and a proper solution to this problem would require
that (again, because a script for an interface of type "bridge" is
accepted by xen, but not by qemu).
2012-01-06 17:59:47 +00:00
|
|
|
def->script);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->data.ethernet.ipaddr != NULL)
|
|
|
|
virBufferEscapeSexpr(buf, "(ip '%s')", def->data.ethernet.ipaddr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
2012-02-15 17:37:15 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
2011-02-21 13:40:09 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->ifname != NULL &&
|
|
|
|
!STRPREFIX(def->ifname, "vif"))
|
|
|
|
virBufferEscapeSexpr(buf, "(vifname '%s')", def->ifname);
|
|
|
|
|
|
|
|
if (!hvm) {
|
|
|
|
if (def->model != NULL)
|
|
|
|
virBufferEscapeSexpr(buf, "(model '%s')", def->model);
|
|
|
|
}
|
|
|
|
else {
|
2012-04-13 13:14:56 +00:00
|
|
|
if (def->model != NULL && STREQ(def->model, "netfront")) {
|
|
|
|
virBufferAddLit(buf, "(type netfront)");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (def->model != NULL) {
|
|
|
|
virBufferEscapeSexpr(buf, "(model '%s')", def->model);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* apparently (type ioemu) breaks paravirt drivers on HVM so skip
|
|
|
|
* this from XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU
|
|
|
|
*/
|
|
|
|
if (xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU) {
|
|
|
|
virBufferAddLit(buf, "(type ioemu)");
|
|
|
|
}
|
|
|
|
}
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!isAttach)
|
|
|
|
virBufferAddLit(buf, ")");
|
|
|
|
|
|
|
|
virBufferAddLit(buf, ")");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/**
|
|
|
|
* xenFormatSxprPCI:
|
|
|
|
* @def: the device config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
*
|
|
|
|
* Convert a single PCI device part of the domain config into a S-expresssion in buf.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
static void
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprPCI(virDomainHostdevDefPtr def,
|
|
|
|
virBufferPtr buf)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
|
2013-03-18 19:56:12 +00:00
|
|
|
def->source.subsys.u.pci.addr.domain,
|
|
|
|
def->source.subsys.u.pci.addr.bus,
|
|
|
|
def->source.subsys.u.pci.addr.slot,
|
|
|
|
def->source.subsys.u.pci.addr.function);
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenFormatSxprOnePCI:
|
|
|
|
* @def: the device config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
* @detach: create expression for device detach (1).
|
|
|
|
*
|
|
|
|
* Convert a single PCI device part of the domain config into a S-expresssion in buf.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprOnePCI(virDomainHostdevDefPtr def,
|
|
|
|
virBufferPtr buf,
|
|
|
|
int detach)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
if (def->managed) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("managed PCI devices not supported with XenD"));
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "(pci ");
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprPCI(def, buf);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (detach)
|
|
|
|
virBufferAddLit(buf, "(state 'Closing')");
|
|
|
|
else
|
|
|
|
virBufferAddLit(buf, "(state 'Initialising')");
|
|
|
|
virBufferAddLit(buf, ")");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenFormatSxprAllPCI:
|
|
|
|
* @def: the domain config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
*
|
|
|
|
* Convert all PCI device parts of the domain config into a S-expresssion in buf.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprAllPCI(virDomainDefPtr def,
|
|
|
|
virBufferPtr buf)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
int hasPCI = 0;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-21 13:40:09 +00:00
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->nhostdevs; i++)
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
|
def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
|
hasPCI = 1;
|
|
|
|
|
|
|
|
if (!hasPCI)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* With the (domain ...) block we have the following odd setup
|
|
|
|
*
|
|
|
|
* (device
|
|
|
|
* (pci
|
|
|
|
* (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
|
|
|
|
* (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
|
|
|
|
* )
|
|
|
|
* )
|
|
|
|
*
|
|
|
|
* Normally there is one (device ...) block per device, but in the
|
|
|
|
* weird world of Xen PCI, one (device ...) covers multiple devices.
|
|
|
|
*/
|
|
|
|
|
|
|
|
virBufferAddLit(buf, "(device (pci ");
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->nhostdevs; i++) {
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
|
def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
|
|
|
|
if (def->hostdevs[i]->managed) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("managed PCI devices not supported with XenD"));
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprPCI(def->hostdevs[i], buf);
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
virBufferAddLit(buf, "))");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* xenFormatSxprSound:
|
|
|
|
* @def: the domain config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
*
|
|
|
|
* Convert all sound device parts of the domain config into S-expression in buf.
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprSound(virDomainDefPtr def,
|
|
|
|
virBufferPtr buf)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
const char *str;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-21 13:40:09 +00:00
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->nsounds; i++) {
|
2011-02-21 13:40:09 +00:00
|
|
|
if (!(str = virDomainSoundModelTypeToString(def->sounds[i]->model))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected sound model %d"),
|
|
|
|
def->sounds[i]->model);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (i)
|
|
|
|
virBufferAddChar(buf, ',');
|
|
|
|
virBufferEscapeSexpr(buf, "%s", str);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virBufferError(buf)) {
|
|
|
|
virReportOOMError();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-17 08:26:13 +00:00
|
|
|
/**
|
|
|
|
* xenFormatSxprInput:
|
|
|
|
* @input: the input config
|
|
|
|
* @buf: a buffer for the result S-expression
|
|
|
|
*
|
|
|
|
* Convert all input device parts of the domain config into S-expression in buf.
|
|
|
|
*
|
|
|
|
* Returns 0 if successful or -1 if failed.
|
|
|
|
*/
|
2011-02-21 13:40:09 +00:00
|
|
|
static int
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprInput(virDomainInputDefPtr input,
|
|
|
|
virBufferPtr buf)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
if (input->bus != VIR_DOMAIN_INPUT_BUS_USB)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (input->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
|
|
|
|
input->type != VIR_DOMAIN_INPUT_TYPE_TABLET) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected input type %d"), input->type);
|
2011-02-21 13:40:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "(usbdevice %s)",
|
2011-02-21 13:40:09 +00:00
|
|
|
input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ?
|
|
|
|
"mouse" : "tablet");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
|
|
|
|
either 32, or 64 on a platform where long is big enough. */
|
|
|
|
verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);
|
|
|
|
|
|
|
|
/**
|
2011-02-21 13:40:12 +00:00
|
|
|
* xenFormatSxpr:
|
2011-02-21 13:40:09 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
|
|
|
* @def: domain config definition
|
|
|
|
* @xendConfigVersion: xend configuration file format
|
|
|
|
*
|
2012-01-17 08:26:13 +00:00
|
|
|
* Generate an S-expression representing the domain configuration.
|
2011-02-21 13:40:09 +00:00
|
|
|
*
|
|
|
|
* Returns the 0 terminated S-Expr string or NULL in case of error.
|
|
|
|
* the caller must free() the returned value.
|
|
|
|
*/
|
|
|
|
char *
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxpr(virConnectPtr conn,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
int xendConfigVersion)
|
2011-02-21 13:40:09 +00:00
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
const char *tmp;
|
|
|
|
char *bufout;
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
int hvm = 0, vmlocaltime = -1;
|
|
|
|
size_t i;
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
bool in_image = false;
|
2011-02-21 13:40:09 +00:00
|
|
|
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_DEBUG("Formatting domain sexpr");
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
virBufferAddLit(&buf, "(vm ");
|
|
|
|
virBufferEscapeSexpr(&buf, "(name '%s')", def->name);
|
2012-03-02 20:27:39 +00:00
|
|
|
virBufferAsprintf(&buf, "(memory %llu)(maxmem %llu)",
|
2011-02-21 13:40:09 +00:00
|
|
|
VIR_DIV_UP(def->mem.cur_balloon, 1024),
|
|
|
|
VIR_DIV_UP(def->mem.max_balloon, 1024));
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
|
2011-02-21 13:40:09 +00:00
|
|
|
/* 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)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(vcpu_avail %lu)", (1UL << def->vcpus) - 1);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (def->cpumask) {
|
2012-09-14 07:47:01 +00:00
|
|
|
char *ranges = virBitmapFormat(def->cpumask);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (ranges == NULL)
|
|
|
|
goto error;
|
|
|
|
virBufferEscapeSexpr(&buf, "(cpus '%s')", ranges);
|
|
|
|
VIR_FREE(ranges);
|
|
|
|
}
|
|
|
|
|
|
|
|
virUUIDFormat(def->uuid, uuidstr);
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(uuid '%s')", uuidstr);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (def->description)
|
|
|
|
virBufferEscapeSexpr(&buf, "(description '%s')", def->description);
|
|
|
|
|
|
|
|
if (def->os.bootloader) {
|
|
|
|
if (def->os.bootloader[0])
|
|
|
|
virBufferEscapeSexpr(&buf, "(bootloader '%s')", def->os.bootloader);
|
|
|
|
else
|
|
|
|
virBufferAddLit(&buf, "(bootloader)");
|
|
|
|
|
|
|
|
if (def->os.bootloaderArgs)
|
|
|
|
virBufferEscapeSexpr(&buf, "(bootloader_args '%s')", def->os.bootloaderArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp = virDomainLifecycleTypeToString(def->onPoweroff))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected lifecycle value %d"), def->onPoweroff);
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(on_poweroff '%s')", tmp);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (!(tmp = virDomainLifecycleTypeToString(def->onReboot))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected lifecycle value %d"), def->onReboot);
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(on_reboot '%s')", tmp);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (!(tmp = virDomainLifecycleCrashTypeToString(def->onCrash))) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected lifecycle value %d"), def->onCrash);
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(on_crash '%s')", tmp);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
if (STREQ(def->os.type, "hvm"))
|
|
|
|
hvm = 1;
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (!def->os.bootloader) {
|
|
|
|
if (hvm)
|
|
|
|
virBufferAddLit(&buf, "(image (hvm ");
|
|
|
|
else
|
|
|
|
virBufferAddLit(&buf, "(image (linux ");
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
in_image = true;
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
if (hvm &&
|
|
|
|
def->os.loader == NULL) {
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",_("no HVM domain loader"));
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->os.kernel)
|
|
|
|
virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.kernel);
|
|
|
|
if (def->os.initrd)
|
|
|
|
virBufferEscapeSexpr(&buf, "(ramdisk '%s')", def->os.initrd);
|
|
|
|
if (def->os.root)
|
|
|
|
virBufferEscapeSexpr(&buf, "(root '%s')", def->os.root);
|
|
|
|
if (def->os.cmdline)
|
|
|
|
virBufferEscapeSexpr(&buf, "(args '%s')", def->os.cmdline);
|
|
|
|
|
|
|
|
if (hvm) {
|
|
|
|
char bootorder[VIR_DOMAIN_BOOT_LAST+1];
|
|
|
|
if (def->os.kernel)
|
|
|
|
virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader);
|
|
|
|
else
|
|
|
|
virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader);
|
|
|
|
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus);
|
2011-02-21 13:40:09 +00:00
|
|
|
if (def->vcpus < def->maxvcpus)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(vcpu_avail %lu)",
|
2011-02-21 13:40:09 +00:00
|
|
|
(1UL << def->vcpus) - 1);
|
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->os.nBootDevs; i++) {
|
2011-02-21 13:40:09 +00:00
|
|
|
switch (def->os.bootDevs[i]) {
|
|
|
|
case VIR_DOMAIN_BOOT_FLOPPY:
|
|
|
|
bootorder[i] = 'a';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case VIR_DOMAIN_BOOT_DISK:
|
|
|
|
bootorder[i] = 'c';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_CDROM:
|
|
|
|
bootorder[i] = 'd';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_NET:
|
|
|
|
bootorder[i] = 'n';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (def->os.nBootDevs == 0) {
|
|
|
|
bootorder[0] = 'c';
|
|
|
|
bootorder[1] = '\0';
|
|
|
|
} else {
|
|
|
|
bootorder[def->os.nBootDevs] = '\0';
|
|
|
|
}
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "(boot %s)", bootorder);
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
/* some disk devices are defined here */
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
2011-02-21 13:40:09 +00:00
|
|
|
switch (def->disks[i]->device) {
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
|
|
|
/* Only xend <= 3.0.2 wants cdrom config here */
|
2012-01-31 17:08:09 +00:00
|
|
|
if (xendConfigVersion != XEND_CONFIG_VERSION_3_0_2)
|
2011-02-21 13:40:09 +00:00
|
|
|
break;
|
|
|
|
if (!STREQ(def->disks[i]->dst, "hdc") ||
|
|
|
|
def->disks[i]->src == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
virBufferEscapeSexpr(&buf, "(cdrom '%s')",
|
|
|
|
def->disks[i]->src);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
|
|
|
/* all xend versions define floppies here */
|
|
|
|
virBufferEscapeSexpr(&buf, "(%s ", def->disks[i]->dst);
|
|
|
|
virBufferEscapeSexpr(&buf, "'%s')", def->disks[i]->src);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
|
|
|
|
virBufferAddLit(&buf, "(acpi 1)");
|
|
|
|
if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
|
|
|
|
virBufferAddLit(&buf, "(apic 1)");
|
|
|
|
if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
|
|
|
|
virBufferAddLit(&buf, "(pae 1)");
|
|
|
|
if (def->features & (1 << VIR_DOMAIN_FEATURE_HAP))
|
|
|
|
virBufferAddLit(&buf, "(hap 1)");
|
2011-06-15 13:27:43 +00:00
|
|
|
if (def->features & (1 << VIR_DOMAIN_FEATURE_VIRIDIAN))
|
|
|
|
virBufferAddLit(&buf, "(viridian 1)");
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
virBufferAddLit(&buf, "(usb 1)");
|
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->ninputs; i++)
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenFormatSxprInput(def->inputs[i], &buf) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (def->parallels) {
|
|
|
|
virBufferAddLit(&buf, "(parallel ");
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenFormatSxprChr(def->parallels[0], &buf) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
virBufferAddLit(&buf, ")");
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(&buf, "(parallel none)");
|
|
|
|
}
|
|
|
|
if (def->serials) {
|
2011-02-25 14:41:12 +00:00
|
|
|
if ((def->nserials > 1) || (def->serials[0]->target.port != 0)) {
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
int maxport = -1, port;
|
|
|
|
size_t j = 0;
|
2011-02-25 14:41:12 +00:00
|
|
|
|
|
|
|
virBufferAddLit(&buf, "(serial (");
|
|
|
|
for (i = 0; i < def->nserials; i++)
|
|
|
|
if (def->serials[i]->target.port > maxport)
|
|
|
|
maxport = def->serials[i]->target.port;
|
|
|
|
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
for (port = 0; port <= maxport; port++) {
|
2011-02-25 14:41:12 +00:00
|
|
|
virDomainChrDefPtr chr = NULL;
|
|
|
|
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
if (port)
|
2011-02-25 14:41:12 +00:00
|
|
|
virBufferAddLit(&buf, " ");
|
|
|
|
for (j = 0; j < def->nserials; j++) {
|
Convert 'int i' to 'size_t i' in src/{xen,xenapi,xenxs} files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
if (def->serials[j]->target.port == port) {
|
2011-02-25 14:41:12 +00:00
|
|
|
chr = def->serials[j];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (chr) {
|
|
|
|
if (xenFormatSxprChr(chr, &buf) < 0)
|
|
|
|
goto error;
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(&buf, "none");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virBufferAddLit(&buf, "))");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
virBufferAddLit(&buf, "(serial ");
|
|
|
|
if (xenFormatSxprChr(def->serials[0], &buf) < 0)
|
|
|
|
goto error;
|
|
|
|
virBufferAddLit(&buf, ")");
|
|
|
|
}
|
2011-02-21 13:40:09 +00:00
|
|
|
} else {
|
|
|
|
virBufferAddLit(&buf, "(serial none)");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->sounds) {
|
|
|
|
virBufferAddLit(&buf, "(soundhw '");
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenFormatSxprSound(def, &buf) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
virBufferAddLit(&buf, "')");
|
|
|
|
}
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
} /* hvm */
|
2011-02-21 13:40:09 +00:00
|
|
|
|
|
|
|
/* get the device emulation model */
|
2012-01-31 17:08:09 +00:00
|
|
|
if (def->emulator && (hvm || xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4))
|
2011-02-21 13:40:09 +00:00
|
|
|
virBufferEscapeSexpr(&buf, "(device_model '%s')", def->emulator);
|
|
|
|
|
2011-05-10 11:24:14 +00:00
|
|
|
/* look for HPET in order to override the hypervisor/xend default */
|
|
|
|
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) {
|
|
|
|
virBufferAsprintf(&buf, "(hpet %d)",
|
|
|
|
def->clock.timers[i]->present);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-02-21 13:40:09 +00:00
|
|
|
|
2012-04-05 16:44:35 +00:00
|
|
|
/* PV graphics for xen <= 3.0.4, or HVM graphics */
|
|
|
|
if (hvm || (xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) {
|
2011-02-21 13:40:09 +00:00
|
|
|
if ((def->ngraphics == 1) &&
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprGraphicsOld(def->graphics[0],
|
|
|
|
&buf, xendConfigVersion) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2011-07-07 01:17:16 +00:00
|
|
|
} else {
|
|
|
|
/* PV domains accept kernel cmdline args */
|
|
|
|
if (def->os.cmdline) {
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
virBufferEscapeSexpr(&buf, "(image (linux (args '%s')", def->os.cmdline);
|
|
|
|
in_image = true;
|
2011-07-07 01:17:16 +00:00
|
|
|
}
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
} /* os.bootloader */
|
|
|
|
|
|
|
|
|
|
|
|
if (xendConfigVersion < XEND_CONFIG_VERSION_3_1_0) {
|
|
|
|
/* <3.1: UTC and LOCALTIME */
|
|
|
|
switch (def->clock.offset) {
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
|
|
|
|
vmlocaltime = 0;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
|
|
|
|
vmlocaltime = 1;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported clock offset='%s'"),
|
|
|
|
virDomainClockOffsetTypeToString(def->clock.offset));
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!in_image) {
|
|
|
|
if (hvm)
|
|
|
|
virBufferAddLit(&buf, "(image (hvm ");
|
|
|
|
else
|
|
|
|
virBufferAddLit(&buf, "(image (linux ");
|
|
|
|
in_image = true;
|
|
|
|
}
|
|
|
|
if (hvm) {
|
|
|
|
/* >=3.1 HV: VARIABLE */
|
|
|
|
int rtc_timeoffset;
|
|
|
|
switch (def->clock.offset) {
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
|
|
|
|
vmlocaltime = (int)def->clock.data.variable.basis;
|
|
|
|
rtc_timeoffset = def->clock.data.variable.adjustment;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
|
|
|
|
if (def->clock.data.utc_reset) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2012-07-18 13:17:20 +00:00
|
|
|
_("unsupported clock adjustment='reset'"));
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
vmlocaltime = 0;
|
|
|
|
rtc_timeoffset = 0;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
|
|
|
|
if (def->clock.data.utc_reset) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
2012-07-18 13:17:20 +00:00
|
|
|
_("unsupported clock adjustment='reset'"));
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
vmlocaltime = 1;
|
|
|
|
rtc_timeoffset = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported clock offset='%s'"),
|
|
|
|
virDomainClockOffsetTypeToString(def->clock.offset));
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
virBufferAsprintf(&buf, "(rtc_timeoffset %d)", rtc_timeoffset);
|
|
|
|
} else {
|
|
|
|
/* >=3.1 PV: UTC and LOCALTIME */
|
|
|
|
switch (def->clock.offset) {
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_UTC:
|
|
|
|
vmlocaltime = 0;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
|
|
|
|
vmlocaltime = 1;
|
|
|
|
break;
|
|
|
|
default:
|
2012-07-18 13:17:20 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported clock offset='%s'"),
|
|
|
|
virDomainClockOffsetTypeToString(def->clock.offset));
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} /* !hvm */
|
|
|
|
/* default post-XenD-3.1 location: */
|
|
|
|
virBufferAsprintf(&buf, "(localtime %d)", vmlocaltime);
|
2011-02-21 13:40:09 +00:00
|
|
|
}
|
Xen: Fix <clock> handling
XenD-3.1 introduced managed domains. HV-domains have rtc_timeoffset
(hgd24f37b31030 from 2007-04-03), which tracks the offset between the
hypervisors clock and the domains RTC, and is persisted by XenD.
In combination with localtime=1 this had a bug until XenD-3.4
(hg5d701be7c37b from 2009-04-01) (I'm not 100% sure how that bug
manifests, but at least for me in TZ=Europe/Berlin I see the previous
offset relative to utc being applied to localtime again, which manifests
in an extra hour being added)
XenD implements the following variants for clock/@offset:
- PV domains don't have a RTC → 'localtime' | 'utc'
- <3.1: no managed domains → 'localtime' | 'utc'
- ≥3.1: the offset is tracked for HV → 'variable'
due to the localtime=1 bug → 'localtime' | 'utc'
- ≥3.4: the offset is tracked for HV → 'variable'
Current libvirtd still thinks XenD only implements <clock offset='utc'/>
and <clock offset='localtime'/>, which is wrong, since the semantic of
'utc' and 'localtime' specifies, that the offset will be reset on
domain-restart, while with 'variable' the offset is kept. (keeping the
offset over "virsh edit" is important, since otherwise the clock might
jump, which confuses certain guest OSs)
xendConfigVersion was last incremented to 4 by the xen-folks for
xen-3.1.0. I know of no way to reliably detect the version of XenD
(user space tools), which may be different from the version of the
hypervisor (kernel) version! Because of this only the change from
'utc'/'localtime' to 'variable' in XenD-3.1 is handled, not the buggy
behaviour of XenD-3.1 until XenD-3.4.
For backward compatibility with previous versions of libvirt Xen-HV
still accepts 'utc' and 'localtime', but they are returned as 'variable'
on the next read-back from Xend to libvirt, since this is what XenD
implements: The RTC is NOT reset back to the specified time on next
restart, but the previous offset is kept.
This behaviour can be turned off by adding the additional attribute
adjustment='reset', in which case libvirt will report an error instead
of doing the conversion. The attribute can also be used as a shortcut to
offset='variable' with basis='...'.
With these changes, it is also necessary to adjust the xen tests:
"localtime = 0" is always inserted, because otherwise on updates the
value is not changed within XenD.
adjustment='reset' is inserted for all cases, since they're all <
XEND_CONFIG_VERSION_3_1_0, only 3.1 introduced persistent
rtc_timeoffset.
Some statements change their order because code was moved around.
Signed-off-by: Philipp Hahn <hahn@univention.de>
2012-02-08 16:32:34 +00:00
|
|
|
if (in_image) {
|
|
|
|
/* closes (image(hvm|linux */
|
|
|
|
virBufferAddLit(&buf, "))");
|
|
|
|
in_image = false;
|
|
|
|
}
|
|
|
|
/* pre-XenD-3.1 and compatibility location */
|
|
|
|
virBufferAsprintf(&buf, "(localtime %d)", vmlocaltime);
|
|
|
|
|
2011-02-21 13:40:09 +00:00
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->ndisks; i++)
|
2011-07-08 21:58:28 +00:00
|
|
|
if (xenFormatSxprDisk(def->disks[i],
|
2011-02-21 13:40:12 +00:00
|
|
|
&buf, hvm, xendConfigVersion, 0) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
|
2013-05-21 07:21:19 +00:00
|
|
|
for (i = 0; i < def->nnets; i++)
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenFormatSxprNet(conn, def->nets[i],
|
|
|
|
&buf, hvm, xendConfigVersion, 0) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
|
2011-02-21 13:40:12 +00:00
|
|
|
if (xenFormatSxprAllPCI(def, &buf) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-04-05 16:44:35 +00:00
|
|
|
/* New style PV graphics config xen >= 3.0.4 */
|
|
|
|
if (!hvm && (xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) {
|
2011-02-21 13:40:09 +00:00
|
|
|
if ((def->ngraphics == 1) &&
|
2011-02-21 13:40:12 +00:00
|
|
|
xenFormatSxprGraphicsNew(def->graphics[0], &buf) < 0)
|
2011-02-21 13:40:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, ")"); /* closes (vm */
|
|
|
|
|
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
bufout = virBufferContentAndReset(&buf);
|
|
|
|
VIR_DEBUG("Formatted sexpr: \n%s", bufout);
|
|
|
|
return bufout;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virBufferFreeAndReset(&buf);
|
|
|
|
return NULL;
|
|
|
|
}
|