2005-12-13 16:22:05 +00:00
|
|
|
/*
|
|
|
|
* xml.c: XML based interfaces for the libvir library
|
|
|
|
*
|
2008-02-04 19:31:30 +00:00
|
|
|
* Copyright (C) 2005, 2007, 2008 Red Hat, Inc.
|
2005-12-13 16:22:05 +00:00
|
|
|
*
|
|
|
|
* See COPYING.LIB for the License of this software
|
|
|
|
*
|
|
|
|
* Daniel Veillard <veillard@redhat.com>
|
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-11-26 11:40:28 +00:00
|
|
|
|
2006-06-26 15:02:18 +00:00
|
|
|
#include "libvirt/libvirt.h"
|
2005-12-13 16:22:05 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
2007-11-26 11:40:28 +00:00
|
|
|
#include <limits.h>
|
2007-03-15 07:43:16 +00:00
|
|
|
#ifdef WITH_XEN
|
2005-12-13 16:22:05 +00:00
|
|
|
#include <xs.h>
|
2007-03-15 07:43:16 +00:00
|
|
|
#endif
|
2007-10-24 14:22:25 +00:00
|
|
|
#include <math.h> /* for isnan() */
|
2005-12-13 16:22:05 +00:00
|
|
|
#include "internal.h"
|
|
|
|
#include "hash.h"
|
2006-02-20 17:22:16 +00:00
|
|
|
#include "sexpr.h"
|
2006-02-16 22:50:52 +00:00
|
|
|
#include "xml.h"
|
2007-06-26 22:33:22 +00:00
|
|
|
#include "buf.h"
|
2008-02-27 04:35:08 +00:00
|
|
|
#include "util.h"
|
2007-10-24 14:22:25 +00:00
|
|
|
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
|
2007-10-22 20:28:55 +00:00
|
|
|
#include "xen_unified.h"
|
2008-05-07 14:04:40 +00:00
|
|
|
#include "xend_internal.h" /* for is_sound_* functions */
|
2005-12-13 16:22:05 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
/**
|
|
|
|
* virXMLError:
|
|
|
|
* @conn: a connection if any
|
|
|
|
* @error: the error number
|
|
|
|
* @info: information/format string
|
|
|
|
* @value: extra integer parameter for the error string
|
|
|
|
*
|
|
|
|
* Report an error coming from the XML module.
|
|
|
|
*/
|
2006-02-27 22:32:54 +00:00
|
|
|
static void
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(virConnectPtr conn, virErrorNumber error, const char *info,
|
|
|
|
int value)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2006-02-27 22:32:54 +00:00
|
|
|
const char *errmsg;
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2006-02-27 22:32:54 +00:00
|
|
|
if (error == VIR_ERR_OK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
errmsg = __virErrorMsg(error, info);
|
2007-02-14 16:16:13 +00:00
|
|
|
__virRaiseError(conn, NULL, NULL, VIR_FROM_XML, error, VIR_ERR_ERROR,
|
2006-03-15 12:13:25 +00:00
|
|
|
errmsg, info, NULL, value, 0, errmsg, info, value);
|
2006-02-27 22:32:54 +00:00
|
|
|
}
|
|
|
|
|
2007-10-22 20:28:55 +00:00
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Parser and converter for the CPUset strings used in libvirt *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
2007-11-30 22:51:54 +00:00
|
|
|
#if WITH_XEN
|
2007-10-22 20:28:55 +00:00
|
|
|
/**
|
|
|
|
* parseCpuNumber:
|
|
|
|
* @str: pointer to the char pointer used
|
|
|
|
* @maxcpu: maximum CPU number allowed
|
|
|
|
*
|
|
|
|
* Parse a CPU number
|
|
|
|
*
|
|
|
|
* Returns the CPU number or -1 in case of error. @str will be
|
|
|
|
* updated to skip the number.
|
|
|
|
*/
|
|
|
|
static int
|
2007-10-24 14:22:25 +00:00
|
|
|
parseCpuNumber(const char **str, int maxcpu)
|
|
|
|
{
|
2007-10-22 20:28:55 +00:00
|
|
|
int ret = 0;
|
|
|
|
const char *cur = *str;
|
|
|
|
|
start using c-ctype functions
Up to now, we've been avoiding ctype functions like isspace, isdigit,
etc. because they are locale-dependent. Now that we have the c-ctype
functions, we can start using *them*, to make the code more readable
with changes like these:
- /* This may not work on EBCDIC. */
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9'))
+ if (c_isalnum(*p))
- while ((*cur >= '0') && (*cur <= '9')) {
+ while (c_isdigit(*cur)) {
Also, some macros in conf.c used names that conflicted with
standard meaning of "BLANK" and "SPACE", so I've adjusted them
to be in line with the definition of e.g., isblank.
In addition, I've wrapped those statement macros with do {...} while (0),
so that we can't forget the ";" after a use. There was one like that
already (fixed below). The missing semicolon would mess up automatic
indenting.
* src/buf.c (virBufferURIEncodeString):
* src/conf.c (IS_EOL, SKIP_BLANKS_AND_EOL, SKIP_BLANKS)
(virConfParseLong, virConfParseValue, virConfParseName)
(virConfParseSeparator, virConfParseStatement, IS_BLANK, IS_CHAR)
(IS_DIGIT, IS_SPACE, SKIP_SPACES):
* src/nodeinfo.c:
* src/qemu_conf.c (qemudParseInterfaceXML):
* src/qemu_driver.c (qemudDomainBlockStats):
* src/sexpr.c:
* src/stats_linux.c:
* src/util.c (virParseNumber, virDiskNameToIndex):
* src/uuid.c (hextobin, virUUIDParse):
* src/virsh.c:
* src/xml.c (parseCpuNumber, virParseCpuSet):
2008-05-16 09:37:44 +00:00
|
|
|
if (!c_isdigit(*cur))
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
2007-10-22 20:28:55 +00:00
|
|
|
|
start using c-ctype functions
Up to now, we've been avoiding ctype functions like isspace, isdigit,
etc. because they are locale-dependent. Now that we have the c-ctype
functions, we can start using *them*, to make the code more readable
with changes like these:
- /* This may not work on EBCDIC. */
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9'))
+ if (c_isalnum(*p))
- while ((*cur >= '0') && (*cur <= '9')) {
+ while (c_isdigit(*cur)) {
Also, some macros in conf.c used names that conflicted with
standard meaning of "BLANK" and "SPACE", so I've adjusted them
to be in line with the definition of e.g., isblank.
In addition, I've wrapped those statement macros with do {...} while (0),
so that we can't forget the ";" after a use. There was one like that
already (fixed below). The missing semicolon would mess up automatic
indenting.
* src/buf.c (virBufferURIEncodeString):
* src/conf.c (IS_EOL, SKIP_BLANKS_AND_EOL, SKIP_BLANKS)
(virConfParseLong, virConfParseValue, virConfParseName)
(virConfParseSeparator, virConfParseStatement, IS_BLANK, IS_CHAR)
(IS_DIGIT, IS_SPACE, SKIP_SPACES):
* src/nodeinfo.c:
* src/qemu_conf.c (qemudParseInterfaceXML):
* src/qemu_driver.c (qemudDomainBlockStats):
* src/sexpr.c:
* src/stats_linux.c:
* src/util.c (virParseNumber, virDiskNameToIndex):
* src/uuid.c (hextobin, virUUIDParse):
* src/virsh.c:
* src/xml.c (parseCpuNumber, virParseCpuSet):
2008-05-16 09:37:44 +00:00
|
|
|
while (c_isdigit(*cur)) {
|
2007-10-22 20:28:55 +00:00
|
|
|
ret = ret * 10 + (*cur - '0');
|
2007-11-05 10:14:42 +00:00
|
|
|
if (ret >= maxcpu)
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
|
|
|
cur++;
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
|
|
|
*str = cur;
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-10-31 09:39:13 +00:00
|
|
|
* virSaveCpuSet:
|
2007-10-22 20:28:55 +00:00
|
|
|
* @conn: connection
|
|
|
|
* @cpuset: pointer to a char array for the CPU set
|
|
|
|
* @maxcpu: number of elements available in @cpuset
|
|
|
|
*
|
|
|
|
* Serialize the cpuset to a string
|
|
|
|
*
|
|
|
|
* Returns the new string NULL in case of error. The string need to be
|
|
|
|
* freed by the caller.
|
|
|
|
*/
|
2007-10-31 09:39:13 +00:00
|
|
|
char *
|
|
|
|
virSaveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
|
2007-10-22 20:28:55 +00:00
|
|
|
{
|
2008-04-28 15:14:59 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2007-10-22 20:28:55 +00:00
|
|
|
int start, cur;
|
|
|
|
int first = 1;
|
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
|
|
|
|
return (NULL);
|
2007-10-22 20:28:55 +00:00
|
|
|
|
|
|
|
cur = 0;
|
|
|
|
start = -1;
|
|
|
|
while (cur < maxcpu) {
|
|
|
|
if (cpuset[cur]) {
|
2007-10-24 14:22:25 +00:00
|
|
|
if (start == -1)
|
|
|
|
start = cur;
|
|
|
|
} else if (start != -1) {
|
|
|
|
if (!first)
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, ",");
|
2007-10-22 20:28:55 +00:00
|
|
|
else
|
2007-10-24 14:22:25 +00:00
|
|
|
first = 0;
|
|
|
|
if (cur == start + 1)
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, "%d", start);
|
2007-10-24 14:22:25 +00:00
|
|
|
else
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, "%d-%d", start, cur - 1);
|
2007-10-24 14:22:25 +00:00
|
|
|
start = -1;
|
|
|
|
}
|
|
|
|
cur++;
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
|
|
|
if (start != -1) {
|
2007-10-24 14:22:25 +00:00
|
|
|
if (!first)
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(&buf, ",");
|
2007-10-24 14:22:25 +00:00
|
|
|
if (maxcpu == start + 1)
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, "%d", start);
|
2007-10-24 14:22:25 +00:00
|
|
|
else
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1);
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
2008-04-28 15:14:59 +00:00
|
|
|
|
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 1000);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virParseCpuSet:
|
2007-10-31 09:39:13 +00:00
|
|
|
* @conn: connection
|
2007-10-22 20:28:55 +00:00
|
|
|
* @str: pointer to a CPU set string pointer
|
|
|
|
* @sep: potential character used to mark the end of string if not 0
|
|
|
|
* @cpuset: pointer to a char array for the CPU set
|
|
|
|
* @maxcpu: number of elements available in @cpuset
|
|
|
|
*
|
|
|
|
* Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
|
|
|
|
* to 1, and 0 otherwise. The syntax allows coma separated entries each
|
|
|
|
* can be either a CPU number, ^N to unset that CPU or N-M for ranges.
|
|
|
|
*
|
|
|
|
* Returns the number of CPU found in that set, or -1 in case of error.
|
|
|
|
* @cpuset is modified accordingly to the value parsed.
|
|
|
|
* @str is updated to the end of the part parsed
|
|
|
|
*/
|
|
|
|
int
|
2007-10-24 14:22:25 +00:00
|
|
|
virParseCpuSet(virConnectPtr conn, const char **str, char sep,
|
|
|
|
char *cpuset, int maxcpu)
|
2007-10-22 20:28:55 +00:00
|
|
|
{
|
|
|
|
const char *cur;
|
|
|
|
int ret = 0;
|
|
|
|
int i, start, last;
|
|
|
|
int neg = 0;
|
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) ||
|
|
|
|
(maxcpu > 100000))
|
|
|
|
return (-1);
|
2007-10-22 20:28:55 +00:00
|
|
|
|
|
|
|
cur = *str;
|
2008-02-27 04:35:08 +00:00
|
|
|
virSkipSpaces(&cur);
|
2007-10-22 20:28:55 +00:00
|
|
|
if (*cur == 0)
|
|
|
|
goto parse_error;
|
|
|
|
|
|
|
|
/* initialize cpumap to all 0s */
|
2007-10-24 14:22:25 +00:00
|
|
|
for (i = 0; i < maxcpu; i++)
|
|
|
|
cpuset[i] = 0;
|
2007-10-22 20:28:55 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
while ((*cur != 0) && (*cur != sep)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
/*
|
|
|
|
* 3 constructs are allowed:
|
|
|
|
* - N : a single CPU number
|
|
|
|
* - N-M : a range of CPU numbers with N < M
|
|
|
|
* - ^N : remove a single CPU number from the current set
|
|
|
|
*/
|
|
|
|
if (*cur == '^') {
|
|
|
|
cur++;
|
|
|
|
neg = 1;
|
|
|
|
}
|
|
|
|
|
start using c-ctype functions
Up to now, we've been avoiding ctype functions like isspace, isdigit,
etc. because they are locale-dependent. Now that we have the c-ctype
functions, we can start using *them*, to make the code more readable
with changes like these:
- /* This may not work on EBCDIC. */
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9'))
+ if (c_isalnum(*p))
- while ((*cur >= '0') && (*cur <= '9')) {
+ while (c_isdigit(*cur)) {
Also, some macros in conf.c used names that conflicted with
standard meaning of "BLANK" and "SPACE", so I've adjusted them
to be in line with the definition of e.g., isblank.
In addition, I've wrapped those statement macros with do {...} while (0),
so that we can't forget the ";" after a use. There was one like that
already (fixed below). The missing semicolon would mess up automatic
indenting.
* src/buf.c (virBufferURIEncodeString):
* src/conf.c (IS_EOL, SKIP_BLANKS_AND_EOL, SKIP_BLANKS)
(virConfParseLong, virConfParseValue, virConfParseName)
(virConfParseSeparator, virConfParseStatement, IS_BLANK, IS_CHAR)
(IS_DIGIT, IS_SPACE, SKIP_SPACES):
* src/nodeinfo.c:
* src/qemu_conf.c (qemudParseInterfaceXML):
* src/qemu_driver.c (qemudDomainBlockStats):
* src/sexpr.c:
* src/stats_linux.c:
* src/util.c (virParseNumber, virDiskNameToIndex):
* src/uuid.c (hextobin, virUUIDParse):
* src/virsh.c:
* src/xml.c (parseCpuNumber, virParseCpuSet):
2008-05-16 09:37:44 +00:00
|
|
|
if (!c_isdigit(*cur))
|
2007-10-24 14:22:25 +00:00
|
|
|
goto parse_error;
|
|
|
|
start = parseCpuNumber(&cur, maxcpu);
|
|
|
|
if (start < 0)
|
|
|
|
goto parse_error;
|
2008-02-27 04:35:08 +00:00
|
|
|
virSkipSpaces(&cur);
|
2007-10-24 14:22:25 +00:00
|
|
|
if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
|
|
|
|
if (neg) {
|
|
|
|
if (cpuset[start] == 1) {
|
|
|
|
cpuset[start] = 0;
|
|
|
|
ret--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (cpuset[start] == 0) {
|
|
|
|
cpuset[start] = 1;
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (*cur == '-') {
|
|
|
|
if (neg)
|
|
|
|
goto parse_error;
|
|
|
|
cur++;
|
2008-02-27 04:35:08 +00:00
|
|
|
virSkipSpaces(&cur);
|
2007-10-24 14:22:25 +00:00
|
|
|
last = parseCpuNumber(&cur, maxcpu);
|
|
|
|
if (last < start)
|
|
|
|
goto parse_error;
|
|
|
|
for (i = start; i <= last; i++) {
|
|
|
|
if (cpuset[i] == 0) {
|
|
|
|
cpuset[i] = 1;
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
}
|
2008-02-27 04:35:08 +00:00
|
|
|
virSkipSpaces(&cur);
|
2007-10-24 14:22:25 +00:00
|
|
|
}
|
|
|
|
if (*cur == ',') {
|
|
|
|
cur++;
|
2008-02-27 04:35:08 +00:00
|
|
|
virSkipSpaces(&cur);
|
2007-10-24 14:22:25 +00:00
|
|
|
neg = 0;
|
|
|
|
} else if ((*cur == 0) || (*cur == sep)) {
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
goto parse_error;
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
|
|
|
*str = cur;
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-10-22 20:28:55 +00:00
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
parse_error:
|
2007-10-22 20:28:55 +00:00
|
|
|
virXMLError(conn, VIR_ERR_XEN_CALL,
|
2007-10-24 14:22:25 +00:00
|
|
|
_("topology cpuset syntax error"), 0);
|
|
|
|
return (-1);
|
2007-10-22 20:28:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-31 09:39:13 +00:00
|
|
|
/**
|
|
|
|
* virConvertCpuSet:
|
|
|
|
* @conn: connection
|
|
|
|
* @str: pointer to a Xen or user provided CPU set string pointer
|
|
|
|
* @maxcpu: number of CPUs on the node, if 0 4096 will be used
|
|
|
|
*
|
|
|
|
* Parse the given CPU set string and convert it to a range based
|
|
|
|
* string.
|
|
|
|
*
|
|
|
|
* Returns a new string which must be freed by the caller or NULL in
|
|
|
|
* case of error.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) {
|
|
|
|
int ret;
|
|
|
|
char *res, *cpuset;
|
|
|
|
const char *cur = str;
|
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
if (maxcpu <= 0)
|
|
|
|
maxcpu = 4096;
|
|
|
|
|
2007-12-11 21:57:29 +00:00
|
|
|
cpuset = calloc(maxcpu, sizeof(*cpuset));
|
2007-10-31 09:39:13 +00:00
|
|
|
if (cpuset == NULL) {
|
2008-04-10 16:54:54 +00:00
|
|
|
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
|
|
|
|
return(NULL);
|
2007-10-31 09:39:13 +00:00
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2007-10-31 09:39:13 +00:00
|
|
|
ret = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
|
|
|
|
if (ret < 0) {
|
|
|
|
free(cpuset);
|
2008-04-10 16:54:54 +00:00
|
|
|
return(NULL);
|
2007-10-31 09:39:13 +00:00
|
|
|
}
|
|
|
|
res = virSaveCpuSet(conn, cpuset, maxcpu);
|
|
|
|
free(cpuset);
|
|
|
|
return (res);
|
|
|
|
}
|
2008-05-07 14:04:40 +00:00
|
|
|
|
2008-05-07 18:50:23 +00:00
|
|
|
#ifndef PROXY
|
2008-05-07 14:04:40 +00:00
|
|
|
/**
|
|
|
|
* virBuildSoundStringFromXML
|
|
|
|
* @sound buffer to populate
|
|
|
|
* @len size of preallocated buffer 'sound'
|
|
|
|
* @ctxt xml context to pull sound info from
|
|
|
|
*
|
|
|
|
* Builds a string of the form m1,m2,m3 from the different sound models
|
|
|
|
* in the xml. String must be free'd by caller.
|
|
|
|
*
|
|
|
|
* Returns string on success, NULL on error
|
|
|
|
*/
|
|
|
|
char * virBuildSoundStringFromXML(virConnectPtr conn,
|
|
|
|
xmlXPathContextPtr ctxt) {
|
|
|
|
|
|
|
|
int nb_nodes, size = 256;
|
|
|
|
char *sound;
|
|
|
|
xmlNodePtr *nodes = NULL;
|
|
|
|
|
|
|
|
if (!(sound = calloc(1, size+1))) {
|
|
|
|
virXMLError(conn, VIR_ERR_NO_MEMORY,
|
|
|
|
_("failed to allocate sound string"), 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
nb_nodes = virXPathNodeSet("/domain/devices/sound", ctxt, &nodes);
|
|
|
|
if (nb_nodes > 0) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < nb_nodes && size > 0; i++) {
|
|
|
|
char *model = NULL;
|
|
|
|
int collision = 0;
|
|
|
|
|
|
|
|
model = (char *) xmlGetProp(nodes[i], (xmlChar *) "model");
|
|
|
|
if (!model) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("no model for sound device"), 0);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_sound_model_valid(model)) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("unknown sound model type"), 0);
|
|
|
|
free(model);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for duplicates in currently built string
|
|
|
|
if (*sound)
|
|
|
|
collision = is_sound_model_conflict(model, sound);
|
|
|
|
|
|
|
|
// If no collision, add to string
|
|
|
|
if (!collision) {
|
|
|
|
if (*sound && (size >= (strlen(model) + 1))) {
|
|
|
|
strncat(sound, ",", size--);
|
|
|
|
} else if (*sound || size < strlen(model)) {
|
|
|
|
free(model);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
strncat(sound, model, size);
|
|
|
|
size -= strlen(model);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(model);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(nodes);
|
|
|
|
return sound;
|
|
|
|
|
|
|
|
error:
|
|
|
|
free(nodes);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-05-07 18:50:23 +00:00
|
|
|
#endif /* !PROXY */
|
2007-11-30 22:51:54 +00:00
|
|
|
#endif /* WITH_XEN */
|
2007-10-23 15:31:33 +00:00
|
|
|
#ifndef PROXY
|
2007-10-22 20:28:55 +00:00
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Wrappers around libxml2 XPath specific functions *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
/**
|
|
|
|
* virXPathString:
|
|
|
|
* @xpath: the XPath string to evaluate
|
|
|
|
* @ctxt: an XPath context
|
|
|
|
*
|
|
|
|
* Convenience function to evaluate an XPath string
|
|
|
|
*
|
|
|
|
* Returns a new string which must be deallocated by the caller or NULL
|
|
|
|
* if the evaluation failed.
|
|
|
|
*/
|
|
|
|
char *
|
2007-10-24 14:22:25 +00:00
|
|
|
virXPathString(const char *xpath, xmlXPathContextPtr ctxt)
|
|
|
|
{
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathObjectPtr obj;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("Invalid parameter to virXPathString()"), 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (NULL);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
2007-07-31 14:27:12 +00:00
|
|
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
2008-02-07 16:49:29 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (NULL);
|
2007-07-31 14:27:12 +00:00
|
|
|
}
|
2007-04-06 12:28:24 +00:00
|
|
|
ret = strdup((char *) obj->stringval);
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
if (ret == NULL) {
|
2008-02-04 19:31:30 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_NO_MEMORY, _("strdup failed"), 0);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virXPathNumber:
|
|
|
|
* @xpath: the XPath string to evaluate
|
|
|
|
* @ctxt: an XPath context
|
|
|
|
* @value: the returned double value
|
|
|
|
*
|
|
|
|
* Convenience function to evaluate an XPath number
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success in which case @value is set,
|
|
|
|
* or -1 if the evaluation failed.
|
|
|
|
*/
|
|
|
|
int
|
2007-10-24 14:22:25 +00:00
|
|
|
virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value)
|
|
|
|
{
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathObjectPtr obj;
|
|
|
|
|
|
|
|
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("Invalid parameter to virXPathNumber()"), 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
|
|
|
|
(isnan(obj->floatval))) {
|
2007-10-24 14:22:25 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
*value = obj->floatval;
|
|
|
|
xmlXPathFreeObject(obj);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (0);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virXPathLong:
|
|
|
|
* @xpath: the XPath string to evaluate
|
|
|
|
* @ctxt: an XPath context
|
|
|
|
* @value: the returned long value
|
|
|
|
*
|
|
|
|
* Convenience function to evaluate an XPath number
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success in which case @value is set,
|
2007-04-06 15:34:09 +00:00
|
|
|
* or -1 if the XPath evaluation failed or -2 if the
|
|
|
|
* value doesn't have a long format.
|
2007-04-06 12:28:24 +00:00
|
|
|
*/
|
|
|
|
int
|
2007-10-24 14:22:25 +00:00
|
|
|
virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value)
|
|
|
|
{
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathObjectPtr obj;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("Invalid parameter to virXPathNumber()"), 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
|
|
|
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
|
|
|
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
|
|
|
char *conv = NULL;
|
2007-10-24 14:22:25 +00:00
|
|
|
long val;
|
2007-04-06 12:28:24 +00:00
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
val = strtol((const char *) obj->stringval, &conv, 10);
|
|
|
|
if (conv == (const char *) obj->stringval) {
|
2007-04-06 12:28:24 +00:00
|
|
|
ret = -2;
|
|
|
|
} else {
|
2007-10-24 14:22:25 +00:00
|
|
|
*value = val;
|
|
|
|
}
|
2007-04-06 12:28:24 +00:00
|
|
|
} else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
|
|
|
|
(!(isnan(obj->floatval)))) {
|
2007-10-24 14:22:25 +00:00
|
|
|
*value = (long) obj->floatval;
|
|
|
|
if (*value != obj->floatval) {
|
|
|
|
ret = -2;
|
|
|
|
}
|
2007-04-06 12:28:24 +00:00
|
|
|
} else {
|
2007-10-24 14:22:25 +00:00
|
|
|
ret = -1;
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virXPathBoolean:
|
|
|
|
* @xpath: the XPath string to evaluate
|
|
|
|
* @ctxt: an XPath context
|
|
|
|
*
|
|
|
|
* Convenience function to evaluate an XPath boolean
|
|
|
|
*
|
|
|
|
* Returns 0 if false, 1 if true, or -1 if the evaluation failed.
|
|
|
|
*/
|
|
|
|
int
|
2007-10-24 14:22:25 +00:00
|
|
|
virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt)
|
|
|
|
{
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathObjectPtr obj;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("Invalid parameter to virXPathBoolean()"), 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN) ||
|
|
|
|
(obj->boolval < 0) || (obj->boolval > 1)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
ret = obj->boolval;
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathFreeObject(obj);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virXPathNode:
|
|
|
|
* @xpath: the XPath string to evaluate
|
|
|
|
* @ctxt: an XPath context
|
|
|
|
*
|
|
|
|
* Convenience function to evaluate an XPath node set and returning
|
|
|
|
* only one node, the first one in the set if any
|
|
|
|
*
|
|
|
|
* Returns a pointer to the node or NULL if the evaluation failed.
|
|
|
|
*/
|
|
|
|
xmlNodePtr
|
2007-10-24 14:22:25 +00:00
|
|
|
virXPathNode(const char *xpath, xmlXPathContextPtr ctxt)
|
|
|
|
{
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathObjectPtr obj;
|
|
|
|
xmlNodePtr ret;
|
|
|
|
|
|
|
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("Invalid parameter to virXPathNode()"), 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (NULL);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
|
|
|
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
|
2007-10-24 14:22:25 +00:00
|
|
|
(obj->nodesetval->nodeTab == NULL)) {
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
return (NULL);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
ret = obj->nodesetval->nodeTab[0];
|
|
|
|
xmlXPathFreeObject(obj);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
/**
|
|
|
|
* virXPathNodeSet:
|
|
|
|
* @xpath: the XPath string to evaluate
|
|
|
|
* @ctxt: an XPath context
|
|
|
|
* @list: the returned list of nodes (or NULL if only count matters)
|
|
|
|
*
|
|
|
|
* Convenience function to evaluate an XPath node set
|
|
|
|
*
|
|
|
|
* Returns the number of nodes found in which case @list is set (and
|
|
|
|
* must be freed) or -1 if the evaluation failed.
|
|
|
|
*/
|
|
|
|
int
|
2007-10-24 14:22:25 +00:00
|
|
|
virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt,
|
|
|
|
xmlNodePtr ** list)
|
|
|
|
{
|
2007-04-06 12:28:24 +00:00
|
|
|
xmlXPathObjectPtr obj;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("Invalid parameter to virXPathNodeSet()"), 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
|
|
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
|
|
|
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
|
2007-10-24 14:22:25 +00:00
|
|
|
(obj->nodesetval->nodeTab == NULL)) {
|
|
|
|
xmlXPathFreeObject(obj);
|
|
|
|
if (list != NULL)
|
|
|
|
*list = NULL;
|
|
|
|
return (-1);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
ret = obj->nodesetval->nodeNr;
|
|
|
|
if (list != NULL) {
|
2007-12-11 21:57:29 +00:00
|
|
|
*list = malloc(ret * sizeof(**list));
|
2007-10-24 14:22:25 +00:00
|
|
|
if (*list == NULL) {
|
|
|
|
virXMLError(NULL, VIR_ERR_NO_MEMORY,
|
|
|
|
_("allocate string array"),
|
2007-12-11 21:57:29 +00:00
|
|
|
ret * sizeof(**list));
|
2007-10-24 14:22:25 +00:00
|
|
|
} else {
|
|
|
|
memcpy(*list, obj->nodesetval->nodeTab,
|
|
|
|
ret * sizeof(xmlNodePtr));
|
|
|
|
}
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
xmlXPathFreeObject(obj);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (ret);
|
2007-04-06 12:28:24 +00:00
|
|
|
}
|
|
|
|
|
2007-10-22 20:28:55 +00:00
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Converter functions to go from the XML tree to an S-Expr for Xen *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
2007-11-30 22:51:54 +00:00
|
|
|
#if WITH_XEN
|
2006-08-26 15:30:44 +00:00
|
|
|
/**
|
2006-12-13 14:08:51 +00:00
|
|
|
* virtDomainParseXMLGraphicsDescImage:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-08-26 15:30:44 +00:00
|
|
|
* @node: node containing graphics description
|
|
|
|
* @buf: a buffer for the result S-Expr
|
2006-09-12 01:34:26 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2006-08-26 15:30:44 +00:00
|
|
|
*
|
2007-02-07 13:50:18 +00:00
|
|
|
* Parse the graphics part of the XML description and add it to the S-Expr
|
|
|
|
* in buf. 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
|
2006-08-26 15:30:44 +00:00
|
|
|
* valid over time.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error
|
|
|
|
*/
|
2007-10-24 14:22:25 +00:00
|
|
|
static int
|
|
|
|
virDomainParseXMLGraphicsDescImage(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
xmlNodePtr node, virBufferPtr buf,
|
|
|
|
int xendConfigVersion)
|
2006-08-26 15:30:44 +00:00
|
|
|
{
|
|
|
|
xmlChar *graphics_type = NULL;
|
|
|
|
|
|
|
|
graphics_type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (graphics_type != NULL) {
|
|
|
|
if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
|
2008-02-05 16:21:25 +00:00
|
|
|
virBufferAddLit(buf, "(sdl 1)");
|
2006-12-13 14:08:51 +00:00
|
|
|
/* TODO:
|
|
|
|
* Need to understand sdl options
|
|
|
|
*
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
*virBufferAddLit(buf, "(display localhost:10.0)");
|
|
|
|
*virBufferAddLit(buf, "(xauthority /root/.Xauthority)");
|
2006-12-13 14:08:51 +00:00
|
|
|
*/
|
2007-10-24 14:22:25 +00:00
|
|
|
} else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(vnc 1)");
|
2006-09-12 01:34:26 +00:00
|
|
|
if (xendConfigVersion >= 2) {
|
2006-10-06 15:32:48 +00:00
|
|
|
xmlChar *vncport = xmlGetProp(node, BAD_CAST "port");
|
2006-12-13 14:08:51 +00:00
|
|
|
xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen");
|
|
|
|
xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd");
|
2007-03-06 20:00:17 +00:00
|
|
|
xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap");
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2006-09-12 01:34:26 +00:00
|
|
|
if (vncport != NULL) {
|
2007-10-24 14:22:25 +00:00
|
|
|
long port = strtol((const char *) vncport, NULL, 10);
|
|
|
|
|
2006-09-12 01:34:26 +00:00
|
|
|
if (port == -1)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(vncunused 1)");
|
2007-03-08 08:55:56 +00:00
|
|
|
else if (port >= 5900)
|
2007-10-24 14:22:25 +00:00
|
|
|
virBufferVSprintf(buf, "(vncdisplay %ld)",
|
|
|
|
port - 5900);
|
2006-10-06 15:32:48 +00:00
|
|
|
xmlFree(vncport);
|
2006-09-12 01:34:26 +00:00
|
|
|
}
|
2006-12-13 14:08:51 +00:00
|
|
|
if (vnclisten != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
|
|
|
|
xmlFree(vnclisten);
|
|
|
|
}
|
|
|
|
if (vncpasswd != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
|
|
|
|
xmlFree(vncpasswd);
|
|
|
|
}
|
2007-03-06 20:00:17 +00:00
|
|
|
if (keymap != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(keymap %s)", keymap);
|
|
|
|
xmlFree(keymap);
|
|
|
|
}
|
2006-09-12 01:34:26 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-26 15:30:44 +00:00
|
|
|
xmlFree(graphics_type);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-13 14:08:51 +00:00
|
|
|
/**
|
|
|
|
* virtDomainParseXMLGraphicsDescVFB:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-12-13 14:08:51 +00:00
|
|
|
* @node: node containing graphics description
|
|
|
|
* @buf: a buffer for the result S-Expr
|
|
|
|
*
|
2007-02-07 13:50:18 +00:00
|
|
|
* Parse the graphics part of the XML description and add it to the S-Expr
|
|
|
|
* in buf. 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
|
2006-12-13 14:08:51 +00:00
|
|
|
* valid over time.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error
|
|
|
|
*/
|
2007-10-24 14:22:25 +00:00
|
|
|
static int
|
|
|
|
virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
xmlNodePtr node, virBufferPtr buf)
|
2006-12-13 14:08:51 +00:00
|
|
|
{
|
|
|
|
xmlChar *graphics_type = NULL;
|
|
|
|
|
|
|
|
graphics_type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (graphics_type != NULL) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(device (vkbd))");
|
|
|
|
virBufferAddLit(buf, "(device (vfb ");
|
2006-12-13 14:08:51 +00:00
|
|
|
if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(type sdl)");
|
2006-12-13 14:08:51 +00:00
|
|
|
/* TODO:
|
|
|
|
* Need to understand sdl options
|
|
|
|
*
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
*virBufferAddLit(buf, "(display localhost:10.0)");
|
|
|
|
*virBufferAddLit(buf, "(xauthority /root/.Xauthority)");
|
2006-12-13 14:08:51 +00:00
|
|
|
*/
|
2007-10-24 14:22:25 +00:00
|
|
|
} else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(type vnc)");
|
2006-12-13 14:08:51 +00:00
|
|
|
xmlChar *vncport = xmlGetProp(node, BAD_CAST "port");
|
|
|
|
xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen");
|
|
|
|
xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd");
|
2007-03-06 20:00:17 +00:00
|
|
|
xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap");
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2006-12-13 14:08:51 +00:00
|
|
|
if (vncport != NULL) {
|
2007-10-24 14:22:25 +00:00
|
|
|
long port = strtol((const char *) vncport, NULL, 10);
|
|
|
|
|
2006-12-13 14:08:51 +00:00
|
|
|
if (port == -1)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(vncunused 1)");
|
2007-03-08 08:55:56 +00:00
|
|
|
else if (port >= 5900)
|
2007-10-24 14:22:25 +00:00
|
|
|
virBufferVSprintf(buf, "(vncdisplay %ld)",
|
|
|
|
port - 5900);
|
2006-12-13 14:08:51 +00:00
|
|
|
xmlFree(vncport);
|
|
|
|
}
|
|
|
|
if (vnclisten != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
|
|
|
|
xmlFree(vnclisten);
|
|
|
|
}
|
|
|
|
if (vncpasswd != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
|
|
|
|
xmlFree(vncpasswd);
|
|
|
|
}
|
2007-03-06 20:00:17 +00:00
|
|
|
if (keymap != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(keymap %s)", keymap);
|
|
|
|
xmlFree(keymap);
|
|
|
|
}
|
2006-12-13 14:08:51 +00:00
|
|
|
}
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "))");
|
2006-12-13 14:08:51 +00:00
|
|
|
xmlFree(graphics_type);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-26 14:22:02 +00:00
|
|
|
int
|
|
|
|
virDomainParseXMLOSDescHVMChar(virConnectPtr conn,
|
|
|
|
char *buf,
|
|
|
|
size_t buflen,
|
|
|
|
xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlChar *type = NULL;
|
|
|
|
xmlChar *path = NULL;
|
|
|
|
xmlChar *bindHost = NULL;
|
|
|
|
xmlChar *bindService = NULL;
|
|
|
|
xmlChar *connectHost = NULL;
|
|
|
|
xmlChar *connectService = NULL;
|
|
|
|
xmlChar *mode = NULL;
|
|
|
|
xmlChar *protocol = NULL;
|
|
|
|
xmlNodePtr cur;
|
|
|
|
|
|
|
|
type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
|
|
|
|
if (type != NULL) {
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
|
|
|
if (xmlStrEqual(cur->name, BAD_CAST "source")) {
|
|
|
|
if (mode == NULL)
|
|
|
|
mode = xmlGetProp(cur, BAD_CAST "mode");
|
|
|
|
|
|
|
|
if (STREQ((const char *)type, "dev") ||
|
|
|
|
STREQ((const char *)type, "file") ||
|
|
|
|
STREQ((const char *)type, "pipe") ||
|
|
|
|
STREQ((const char *)type, "unix")) {
|
|
|
|
if (path == NULL)
|
|
|
|
path = xmlGetProp(cur, BAD_CAST "path");
|
|
|
|
|
|
|
|
} else if (STREQ((const char *)type, "udp") ||
|
|
|
|
STREQ((const char *)type, "tcp")) {
|
|
|
|
if (mode == NULL ||
|
|
|
|
STREQ((const char *)mode, "connect")) {
|
|
|
|
|
|
|
|
if (connectHost == NULL)
|
|
|
|
connectHost = xmlGetProp(cur, BAD_CAST "host");
|
|
|
|
if (connectService == NULL)
|
|
|
|
connectService = xmlGetProp(cur, BAD_CAST "service");
|
|
|
|
} else {
|
|
|
|
if (bindHost == NULL)
|
|
|
|
bindHost = xmlGetProp(cur, BAD_CAST "host");
|
|
|
|
if (bindService == NULL)
|
|
|
|
bindService = xmlGetProp(cur, BAD_CAST "service");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ((const char*)type, "udp")) {
|
|
|
|
xmlFree(mode);
|
|
|
|
mode = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
|
|
|
|
if (protocol == NULL)
|
|
|
|
protocol = xmlGetProp(cur, BAD_CAST "type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == NULL ||
|
|
|
|
STREQ((const char *)type, "pty")) {
|
|
|
|
strncpy(buf, "pty", buflen);
|
|
|
|
} else if (STREQ((const char *)type, "null") ||
|
|
|
|
STREQ((const char *)type, "stdio") ||
|
|
|
|
STREQ((const char *)type, "vc")) {
|
|
|
|
snprintf(buf, buflen, "%s", type);
|
|
|
|
} else if (STREQ((const char *)type, "file") ||
|
|
|
|
STREQ((const char *)type, "dev") ||
|
|
|
|
STREQ((const char *)type, "pipe")) {
|
|
|
|
if (path == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing source path attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STREQ((const char *)type, "dev"))
|
|
|
|
strncpy(buf, (const char *)path, buflen);
|
|
|
|
else
|
|
|
|
snprintf(buf, buflen, "%s:%s", type, path);
|
|
|
|
} else if (STREQ((const char *)type, "tcp")) {
|
|
|
|
int telnet = 0;
|
|
|
|
if (protocol != NULL &&
|
|
|
|
STREQ((const char *)protocol, "telnet"))
|
|
|
|
telnet = 1;
|
|
|
|
|
|
|
|
if (mode == NULL ||
|
|
|
|
STREQ((const char *)mode, "connect")) {
|
|
|
|
if (connectHost == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Missing source host attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (connectService == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Missing source service attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, buflen, "%s:%s:%s",
|
|
|
|
(telnet ? "telnet" : "tcp"),
|
|
|
|
connectHost, connectService);
|
|
|
|
} else {
|
|
|
|
if (bindHost == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Missing source host attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (bindService == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Missing source service attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, buflen, "%s:%s:%s,listen",
|
|
|
|
(telnet ? "telnet" : "tcp"),
|
|
|
|
bindHost, bindService);
|
|
|
|
}
|
|
|
|
} else if (STREQ((const char *)type, "udp")) {
|
|
|
|
if (connectService == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing source service attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, buflen, "udp:%s:%s@%s:%s",
|
|
|
|
connectHost ? (const char *)connectHost : "",
|
|
|
|
connectService,
|
|
|
|
bindHost ? (const char *)bindHost : "",
|
|
|
|
bindService ? (const char *)bindService : "");
|
|
|
|
} else if (STREQ((const char *)type, "unix")) {
|
|
|
|
if (path == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing source path attribute for char device"), 0);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode == NULL ||
|
|
|
|
STREQ((const char *)mode, "connect")) {
|
|
|
|
snprintf(buf, buflen, "%s:%s", type, path);
|
|
|
|
} else {
|
|
|
|
snprintf(buf, buflen, "%s:%s,listen", type, path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf[buflen-1] = '\0';
|
|
|
|
|
|
|
|
xmlFree(mode);
|
|
|
|
xmlFree(protocol);
|
|
|
|
xmlFree(type);
|
|
|
|
xmlFree(bindHost);
|
|
|
|
xmlFree(bindService);
|
|
|
|
xmlFree(connectHost);
|
|
|
|
xmlFree(connectService);
|
|
|
|
xmlFree(path);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
xmlFree(mode);
|
|
|
|
xmlFree(protocol);
|
|
|
|
xmlFree(type);
|
|
|
|
xmlFree(bindHost);
|
|
|
|
xmlFree(bindService);
|
|
|
|
xmlFree(connectHost);
|
|
|
|
xmlFree(connectService);
|
|
|
|
xmlFree(path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-02-16 22:50:52 +00:00
|
|
|
/**
|
2006-07-10 11:21:24 +00:00
|
|
|
* virDomainParseXMLOSDescHVM:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-07-10 11:21:24 +00:00
|
|
|
* @node: node containing HVM OS description
|
2006-02-16 22:50:52 +00:00
|
|
|
* @buf: a buffer for the result S-Expr
|
2006-07-10 11:21:24 +00:00
|
|
|
* @ctxt: a path context representing the XML description
|
2007-02-07 13:44:22 +00:00
|
|
|
* @vcpus: number of virtual CPUs to configure
|
2006-09-12 01:16:22 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2008-02-05 16:21:25 +00:00
|
|
|
* @hasKernel: whether the domain is booting from a kernel
|
2006-02-16 22:50:52 +00:00
|
|
|
*
|
2008-02-05 16:21:25 +00:00
|
|
|
* Parse the OS part of the XML description for a HVM domain
|
|
|
|
* and add it to the S-Expr in buf.
|
2006-02-16 22:50:52 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
static int
|
2007-10-24 14:22:25 +00:00
|
|
|
virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node,
|
|
|
|
virBufferPtr buf, xmlXPathContextPtr ctxt,
|
2008-02-05 16:21:25 +00:00
|
|
|
int vcpus, int xendConfigVersion,
|
|
|
|
int hasKernel)
|
2006-07-10 11:21:24 +00:00
|
|
|
{
|
|
|
|
xmlNodePtr cur, txt;
|
2007-07-18 21:08:22 +00:00
|
|
|
xmlNodePtr *nodes = NULL;
|
2006-10-06 15:32:48 +00:00
|
|
|
xmlChar *loader = NULL;
|
2007-04-13 00:43:57 +00:00
|
|
|
char bootorder[5];
|
|
|
|
int nbootorder = 0;
|
2007-07-18 21:08:22 +00:00
|
|
|
int res, nb_nodes;
|
2007-04-06 12:28:24 +00:00
|
|
|
char *str;
|
2006-07-10 11:21:24 +00:00
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
2008-02-05 16:21:25 +00:00
|
|
|
if ((loader == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "loader"))) {
|
2006-07-10 11:21:24 +00:00
|
|
|
txt = cur->children;
|
|
|
|
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
|
2007-02-07 13:50:18 +00:00
|
|
|
(txt->next == NULL))
|
2006-07-10 11:21:24 +00:00
|
|
|
loader = txt->content;
|
2007-04-13 00:43:57 +00:00
|
|
|
} else if ((xmlStrEqual(cur->name, BAD_CAST "boot"))) {
|
|
|
|
xmlChar *boot_dev = xmlGetProp(cur, BAD_CAST "dev");
|
2007-10-24 14:22:25 +00:00
|
|
|
|
|
|
|
if (nbootorder ==
|
|
|
|
((sizeof(bootorder) / sizeof(bootorder[0])) - 1)) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
2008-02-04 19:31:30 +00:00
|
|
|
_("too many boot devices"), 0);
|
2007-04-13 00:43:57 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (xmlStrEqual(boot_dev, BAD_CAST "fd")) {
|
|
|
|
bootorder[nbootorder++] = 'a';
|
|
|
|
} else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) {
|
|
|
|
bootorder[nbootorder++] = 'd';
|
|
|
|
} else if (xmlStrEqual(boot_dev, BAD_CAST "network")) {
|
|
|
|
bootorder[nbootorder++] = 'n';
|
|
|
|
} else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) {
|
|
|
|
bootorder[nbootorder++] = 'c';
|
|
|
|
} else {
|
|
|
|
xmlFree(boot_dev);
|
|
|
|
/* Any other type of boot dev is unsupported right now */
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
xmlFree(boot_dev);
|
2006-07-10 11:21:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
2008-02-05 16:21:25 +00:00
|
|
|
/*
|
|
|
|
* XenD always needs boot order defined for HVM, even if
|
|
|
|
* booting off a kernel + initrd, so force to 'c' if nothing
|
|
|
|
* else is specified
|
|
|
|
*/
|
|
|
|
if (nbootorder == 0)
|
|
|
|
bootorder[nbootorder++] = 'c';
|
2007-04-13 00:43:57 +00:00
|
|
|
bootorder[nbootorder] = '\0';
|
2008-02-05 16:21:25 +00:00
|
|
|
|
2006-07-10 11:21:24 +00:00
|
|
|
if (loader == NULL) {
|
2008-02-05 22:07:31 +00:00
|
|
|
virXMLError(conn, VIR_ERR_INTERNAL_ERROR, _("no HVM domain loader"), 0);
|
2008-02-05 16:21:25 +00:00
|
|
|
return -1;
|
2006-07-10 11:21:24 +00:00
|
|
|
}
|
|
|
|
|
2008-02-05 19:27:37 +00:00
|
|
|
/*
|
2008-02-05 16:21:25 +00:00
|
|
|
* Originally XenD abused the 'kernel' parameter for the HVM
|
|
|
|
* firmware. New XenD allows HVM guests to boot from a kernel
|
|
|
|
* and if this is enabled, the HVM firmware must use the new
|
|
|
|
* 'loader' parameter
|
|
|
|
*/
|
|
|
|
if (hasKernel) {
|
|
|
|
virBufferVSprintf(buf, "(loader '%s')", (const char *) loader);
|
|
|
|
} else {
|
|
|
|
virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
|
2006-07-10 11:21:24 +00:00
|
|
|
}
|
|
|
|
|
2007-02-07 13:44:22 +00:00
|
|
|
virBufferVSprintf(buf, "(vcpus %d)", vcpus);
|
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
if (nbootorder)
|
|
|
|
virBufferVSprintf(buf, "(boot %s)", bootorder);
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
/* get the 1st floppy device file */
|
2007-10-24 14:22:25 +00:00
|
|
|
cur = virXPathNode(
|
|
|
|
"/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
|
|
|
|
ctxt);
|
|
|
|
if (cur != NULL) {
|
2007-04-13 00:43:57 +00:00
|
|
|
xmlChar *fdfile;
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
fdfile = xmlGetProp(cur, BAD_CAST "file");
|
2007-10-24 14:22:25 +00:00
|
|
|
if (fdfile != NULL) {
|
2007-04-13 00:43:57 +00:00
|
|
|
virBufferVSprintf(buf, "(fda '%s')", fdfile);
|
|
|
|
free(fdfile);
|
2007-10-24 14:22:25 +00:00
|
|
|
}
|
2007-04-13 00:43:57 +00:00
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
/* get the 2nd floppy device file */
|
2007-10-24 14:22:25 +00:00
|
|
|
cur = virXPathNode(
|
|
|
|
"/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
|
|
|
|
ctxt);
|
|
|
|
if (cur != NULL) {
|
2007-04-13 00:43:57 +00:00
|
|
|
xmlChar *fdfile;
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
fdfile = xmlGetProp(cur, BAD_CAST "file");
|
2007-10-24 14:22:25 +00:00
|
|
|
if (fdfile != NULL) {
|
2007-04-13 00:43:57 +00:00
|
|
|
virBufferVSprintf(buf, "(fdb '%s')", fdfile);
|
|
|
|
free(fdfile);
|
2007-10-24 14:22:25 +00:00
|
|
|
}
|
2007-04-13 00:43:57 +00:00
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
/* get the cdrom device file */
|
|
|
|
/* Only XenD <= 3.0.2 wants cdrom config here */
|
|
|
|
if (xendConfigVersion == 1) {
|
2007-10-24 14:22:25 +00:00
|
|
|
cur = virXPathNode(
|
2008-04-10 16:54:54 +00:00
|
|
|
"/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source",
|
2007-10-24 14:22:25 +00:00
|
|
|
ctxt);
|
|
|
|
if (cur != NULL) {
|
2007-04-13 00:43:57 +00:00
|
|
|
xmlChar *cdfile;
|
|
|
|
|
|
|
|
cdfile = xmlGetProp(cur, BAD_CAST "file");
|
|
|
|
if (cdfile != NULL) {
|
|
|
|
virBufferVSprintf(buf, "(cdrom '%s')",
|
2007-10-24 14:22:25 +00:00
|
|
|
(const char *) cdfile);
|
2007-04-13 00:43:57 +00:00
|
|
|
xmlFree(cdfile);
|
2007-02-07 13:50:18 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-11 14:40:04 +00:00
|
|
|
}
|
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
if (virXPathNode("/domain/features/acpi", ctxt) != NULL)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(acpi 1)");
|
2007-04-13 00:43:57 +00:00
|
|
|
if (virXPathNode("/domain/features/apic", ctxt) != NULL)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(apic 1)");
|
2007-04-13 00:43:57 +00:00
|
|
|
if (virXPathNode("/domain/features/pae", ctxt) != NULL)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(pae 1)");
|
2007-04-13 00:43:57 +00:00
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(usb 1)");
|
2007-07-18 21:08:22 +00:00
|
|
|
nb_nodes = virXPathNodeSet("/domain/devices/input", ctxt, &nodes);
|
|
|
|
if (nb_nodes > 0) {
|
|
|
|
int i;
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-07-18 21:08:22 +00:00
|
|
|
for (i = 0; i < nb_nodes; i++) {
|
|
|
|
xmlChar *itype = NULL, *bus = NULL;
|
|
|
|
int isMouse = 1;
|
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
itype = xmlGetProp(nodes[i], (xmlChar *) "type");
|
2007-07-18 21:08:22 +00:00
|
|
|
|
|
|
|
if (!itype) {
|
|
|
|
goto error;
|
|
|
|
}
|
2008-05-14 19:51:24 +00:00
|
|
|
if (STREQ((const char *) itype, "tablet"))
|
2007-07-18 21:08:22 +00:00
|
|
|
isMouse = 0;
|
2008-05-14 19:51:24 +00:00
|
|
|
else if (STRNEQ((const char *) itype, "mouse")) {
|
2007-07-18 21:08:22 +00:00
|
|
|
xmlFree(itype);
|
2008-02-04 19:31:30 +00:00
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("invalid input device"), 0);
|
2007-07-18 21:08:22 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
xmlFree(itype);
|
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
bus = xmlGetProp(nodes[i], (xmlChar *) "bus");
|
2007-07-18 21:08:22 +00:00
|
|
|
if (!bus) {
|
|
|
|
if (!isMouse) {
|
|
|
|
/* Nothing - implicit ps2 */
|
|
|
|
} else {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(usbdevice tablet)");
|
2007-07-18 21:08:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-05-14 19:51:24 +00:00
|
|
|
if (STREQ((const char *) bus, "ps2")) {
|
2007-07-18 21:08:22 +00:00
|
|
|
if (!isMouse) {
|
|
|
|
xmlFree(bus);
|
2008-02-04 19:31:30 +00:00
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR,
|
|
|
|
_("invalid input device"), 0);
|
2007-07-18 21:08:22 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
/* Nothing - implicit ps2 */
|
2008-05-14 19:51:24 +00:00
|
|
|
} else if (STREQ((const char *) bus, "usb")) {
|
2007-07-18 21:08:22 +00:00
|
|
|
if (isMouse)
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(usbdevice mouse)");
|
2007-07-18 21:08:22 +00:00
|
|
|
else
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(usbdevice tablet)");
|
2007-07-18 21:08:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlFree(bus);
|
|
|
|
}
|
|
|
|
free(nodes);
|
|
|
|
nodes = NULL;
|
|
|
|
}
|
|
|
|
|
2008-04-26 14:22:02 +00:00
|
|
|
cur = virXPathNode("/domain/devices/parallel[1]", ctxt);
|
|
|
|
if (cur != NULL) {
|
|
|
|
char scratch[PATH_MAX];
|
|
|
|
if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0)
|
|
|
|
goto error;
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(buf, "(parallel %s)", scratch);
|
2008-04-26 14:22:02 +00:00
|
|
|
} else {
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(buf, "(parallel none)");
|
2006-08-11 14:40:04 +00:00
|
|
|
}
|
2008-04-26 14:22:02 +00:00
|
|
|
|
|
|
|
cur = virXPathNode("/domain/devices/serial[1]", ctxt);
|
|
|
|
if (cur != NULL) {
|
|
|
|
char scratch[PATH_MAX];
|
|
|
|
if (virDomainParseXMLOSDescHVMChar(conn, scratch, sizeof(scratch), cur) < 0)
|
|
|
|
goto error;
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferVSprintf(buf, "(serial %s)", scratch);
|
2008-04-26 14:22:02 +00:00
|
|
|
} else {
|
|
|
|
res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
|
|
|
|
if (res < 0) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (res) {
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(buf, "(serial pty)");
|
2008-04-26 14:22:02 +00:00
|
|
|
} else {
|
2008-04-28 15:14:59 +00:00
|
|
|
virBufferAddLit(buf, "(serial none)");
|
2008-04-26 14:22:02 +00:00
|
|
|
}
|
2006-08-11 14:40:04 +00:00
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2008-05-07 14:04:40 +00:00
|
|
|
cur = virXPathNode("/domain/devices/sound", ctxt);
|
|
|
|
if (cur) {
|
|
|
|
char *soundstr;
|
|
|
|
if (!(soundstr = virBuildSoundStringFromXML(conn, ctxt)))
|
|
|
|
goto error;
|
|
|
|
virBufferVSprintf(buf, "(soundhw '%s')", soundstr);
|
|
|
|
free(soundstr);
|
|
|
|
}
|
|
|
|
|
2007-07-16 21:30:30 +00:00
|
|
|
str = virXPathString("string(/domain/clock/@offset)", ctxt);
|
2008-04-28 15:14:59 +00:00
|
|
|
if (str != NULL && STREQ(str, "localtime")) {
|
|
|
|
virBufferAddLit(buf, "(localtime 1)");
|
2007-07-16 21:30:30 +00:00
|
|
|
}
|
2008-01-29 17:41:07 +00:00
|
|
|
free(str);
|
2007-07-16 21:30:30 +00:00
|
|
|
|
2006-07-10 11:21:24 +00:00
|
|
|
return (0);
|
2007-04-13 00:43:57 +00:00
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
error:
|
2008-01-29 17:41:07 +00:00
|
|
|
free(nodes);
|
2007-10-24 14:22:25 +00:00
|
|
|
return (-1);
|
2006-07-10 11:21:24 +00:00
|
|
|
}
|
|
|
|
|
2008-02-05 16:21:25 +00:00
|
|
|
|
2006-07-10 11:21:24 +00:00
|
|
|
/**
|
2008-02-05 16:21:25 +00:00
|
|
|
* virDomainParseXMLOSDescKernel:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-07-10 11:21:24 +00:00
|
|
|
* @node: node containing PV OS description
|
|
|
|
* @buf: a buffer for the result S-Expr
|
|
|
|
*
|
2008-02-05 16:21:25 +00:00
|
|
|
* Parse the OS part of the XML description for a domain using a direct
|
|
|
|
* kernel and initrd to boot.
|
2006-07-10 11:21:24 +00:00
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of error.
|
|
|
|
*/
|
|
|
|
static int
|
2008-02-05 16:21:25 +00:00
|
|
|
virDomainParseXMLOSDescKernel(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
xmlNodePtr node,
|
|
|
|
virBufferPtr buf)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlNodePtr cur, txt;
|
|
|
|
const xmlChar *root = NULL;
|
|
|
|
const xmlChar *kernel = NULL;
|
|
|
|
const xmlChar *initrd = NULL;
|
|
|
|
const xmlChar *cmdline = NULL;
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
2008-02-05 16:21:25 +00:00
|
|
|
if ((kernel == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "kernel"))) {
|
2006-03-15 12:13:25 +00:00
|
|
|
txt = cur->children;
|
2006-07-04 12:46:14 +00:00
|
|
|
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
|
2007-02-07 13:50:18 +00:00
|
|
|
(txt->next == NULL))
|
2006-03-15 12:13:25 +00:00
|
|
|
kernel = txt->content;
|
|
|
|
} else if ((root == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "root"))) {
|
|
|
|
txt = cur->children;
|
2006-07-04 12:46:14 +00:00
|
|
|
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
|
2007-02-07 13:50:18 +00:00
|
|
|
(txt->next == NULL))
|
2006-03-15 12:13:25 +00:00
|
|
|
root = txt->content;
|
|
|
|
} else if ((initrd == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "initrd"))) {
|
|
|
|
txt = cur->children;
|
2006-07-04 12:46:14 +00:00
|
|
|
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
|
2007-02-07 13:50:18 +00:00
|
|
|
(txt->next == NULL))
|
2006-03-15 12:13:25 +00:00
|
|
|
initrd = txt->content;
|
|
|
|
} else if ((cmdline == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "cmdline"))) {
|
|
|
|
txt = cur->children;
|
2006-07-04 12:46:14 +00:00
|
|
|
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
|
2007-02-07 13:50:18 +00:00
|
|
|
(txt->next == NULL))
|
2006-03-15 12:13:25 +00:00
|
|
|
cmdline = txt->content;
|
|
|
|
}
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
cur = cur->next;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-02-05 16:21:25 +00:00
|
|
|
virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
|
|
|
|
|
2006-02-16 22:50:52 +00:00
|
|
|
if (initrd != NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
|
2006-04-26 07:31:16 +00:00
|
|
|
if (root != NULL)
|
2006-02-16 22:50:52 +00:00
|
|
|
virBufferVSprintf(buf, "(root '%s')", (const char *) root);
|
2006-04-26 07:31:16 +00:00
|
|
|
if (cmdline != NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
|
2006-08-26 15:30:44 +00:00
|
|
|
|
2006-03-15 12:13:25 +00:00
|
|
|
return (0);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
|
2006-11-08 16:55:20 +00:00
|
|
|
/**
|
|
|
|
* virCatchXMLParseError:
|
|
|
|
* @ctx: the context
|
|
|
|
* @msg: the error message
|
|
|
|
* @...: extra arguments
|
|
|
|
*
|
|
|
|
* SAX callback on parsing errors, act as a gate for libvirt own
|
|
|
|
* error reporting.
|
|
|
|
*/
|
|
|
|
static void
|
2007-10-24 14:22:25 +00:00
|
|
|
virCatchXMLParseError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
|
|
|
{
|
2006-11-08 16:55:20 +00:00
|
|
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
|
|
|
|
2006-11-17 00:10:51 +00:00
|
|
|
if ((ctxt != NULL) &&
|
2006-11-08 16:55:20 +00:00
|
|
|
(ctxt->lastError.level == XML_ERR_FATAL) &&
|
2006-11-17 00:10:51 +00:00
|
|
|
(ctxt->lastError.message != NULL)) {
|
2007-02-14 16:16:13 +00:00
|
|
|
virXMLError(NULL, VIR_ERR_XML_DETAIL, ctxt->lastError.message,
|
2007-02-07 13:50:18 +00:00
|
|
|
ctxt->lastError.line);
|
2006-11-08 16:55:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-16 22:50:52 +00:00
|
|
|
/**
|
|
|
|
* virDomainParseXMLDiskDesc:
|
2006-07-10 11:21:24 +00:00
|
|
|
* @node: node containing disk description
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-02-16 22:50:52 +00:00
|
|
|
* @buf: a buffer for the result S-Expr
|
2006-09-12 01:16:22 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2006-02-16 22:50:52 +00:00
|
|
|
*
|
|
|
|
* Parse the one disk in the XML description and add it to the S-Expr in buf
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static int
|
2007-10-24 14:22:25 +00:00
|
|
|
virDomainParseXMLDiskDesc(virConnectPtr conn, xmlNodePtr node,
|
|
|
|
virBufferPtr buf, int hvm, int xendConfigVersion)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlNodePtr cur;
|
|
|
|
xmlChar *type = NULL;
|
2006-08-11 14:40:04 +00:00
|
|
|
xmlChar *device = NULL;
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlChar *source = NULL;
|
|
|
|
xmlChar *target = NULL;
|
2006-10-09 14:32:07 +00:00
|
|
|
xmlChar *drvName = NULL;
|
|
|
|
xmlChar *drvType = NULL;
|
2006-02-16 22:50:52 +00:00
|
|
|
int ro = 0;
|
2006-11-13 17:09:31 +00:00
|
|
|
int shareable = 0;
|
2006-02-16 22:50:52 +00:00
|
|
|
int typ = 0;
|
2006-09-12 01:16:22 +00:00
|
|
|
int cdrom = 0;
|
2007-04-11 16:06:30 +00:00
|
|
|
int isNoSrcCdrom = 0;
|
2007-07-11 08:41:11 +00:00
|
|
|
int ret = 0;
|
2006-02-16 22:50:52 +00:00
|
|
|
|
|
|
|
type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (type != NULL) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (xmlStrEqual(type, BAD_CAST "file"))
|
|
|
|
typ = 0;
|
|
|
|
else if (xmlStrEqual(type, BAD_CAST "block"))
|
|
|
|
typ = 1;
|
|
|
|
xmlFree(type);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2006-08-11 14:40:04 +00:00
|
|
|
device = xmlGetProp(node, BAD_CAST "device");
|
2006-10-09 14:32:07 +00:00
|
|
|
|
2006-02-16 22:50:52 +00:00
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if ((source == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
|
|
|
|
|
|
|
if (typ == 0)
|
|
|
|
source = xmlGetProp(cur, BAD_CAST "file");
|
|
|
|
else
|
|
|
|
source = xmlGetProp(cur, BAD_CAST "dev");
|
|
|
|
} else if ((target == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "target"))) {
|
|
|
|
target = xmlGetProp(cur, BAD_CAST "dev");
|
2006-10-09 14:32:07 +00:00
|
|
|
} else if ((drvName == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "driver"))) {
|
|
|
|
drvName = xmlGetProp(cur, BAD_CAST "name");
|
2008-05-14 19:51:24 +00:00
|
|
|
if (drvName && STREQ((const char *) drvName, "tap"))
|
2006-10-09 14:32:07 +00:00
|
|
|
drvType = xmlGetProp(cur, BAD_CAST "type");
|
2006-03-15 12:13:25 +00:00
|
|
|
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
|
|
|
|
ro = 1;
|
2006-11-13 17:09:31 +00:00
|
|
|
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
|
2007-02-07 13:50:18 +00:00
|
|
|
shareable = 1;
|
2006-03-15 12:13:25 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source == NULL) {
|
2007-04-11 16:06:30 +00:00
|
|
|
/* There is a case without the source
|
|
|
|
* to the CD-ROM device
|
|
|
|
*/
|
2008-05-14 19:51:24 +00:00
|
|
|
if (hvm && device && STREQ((const char *) device, "cdrom")) {
|
2007-04-11 16:06:30 +00:00
|
|
|
isNoSrcCdrom = 1;
|
|
|
|
}
|
|
|
|
if (!isNoSrcCdrom) {
|
|
|
|
virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) target, 0);
|
2007-07-11 08:41:11 +00:00
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
2007-04-11 16:06:30 +00:00
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
if (target == NULL) {
|
2007-02-14 16:16:13 +00:00
|
|
|
virXMLError(conn, VIR_ERR_NO_TARGET, (const char *) source, 0);
|
2007-07-11 08:41:11 +00:00
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2006-08-11 14:40:04 +00:00
|
|
|
|
2006-09-12 01:16:22 +00:00
|
|
|
/* Xend (all versions) put the floppy device config
|
|
|
|
* under the hvm (image (os)) block
|
2006-08-11 14:40:04 +00:00
|
|
|
*/
|
2008-05-14 19:51:24 +00:00
|
|
|
if (hvm && device && STREQ((const char *) device, "floppy")) {
|
2006-10-06 15:32:48 +00:00
|
|
|
goto cleanup;
|
2006-09-12 01:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Xend <= 3.0.2 doesn't include cdrom config here */
|
2008-05-14 19:51:24 +00:00
|
|
|
if (hvm && device && STREQ((const char *) device, "cdrom")) {
|
2006-09-12 01:16:22 +00:00
|
|
|
if (xendConfigVersion == 1)
|
2006-10-06 15:32:48 +00:00
|
|
|
goto cleanup;
|
2006-09-12 01:16:22 +00:00
|
|
|
else
|
|
|
|
cdrom = 1;
|
2006-08-11 14:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(device ");
|
2006-10-09 14:32:07 +00:00
|
|
|
/* Normally disks are in a (device (vbd ...)) block
|
2007-10-24 14:22:25 +00:00
|
|
|
* but blktap disks ended up in a differently named
|
|
|
|
* (device (tap ....)) block.... */
|
2008-05-14 19:51:24 +00:00
|
|
|
if (drvName && STREQ((const char *) drvName, "tap")) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(tap ");
|
2006-10-09 14:32:07 +00:00
|
|
|
} else {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(vbd ");
|
2006-10-09 14:32:07 +00:00
|
|
|
}
|
2006-09-12 01:16:22 +00:00
|
|
|
|
2006-08-11 14:40:04 +00:00
|
|
|
if (hvm) {
|
2007-10-24 14:22:25 +00:00
|
|
|
char *tmp = (char *) target;
|
|
|
|
|
2006-09-12 01:16:22 +00:00
|
|
|
/* Just in case user mistakenly still puts ioemu: in their XML */
|
2008-05-14 19:51:24 +00:00
|
|
|
if (STRPREFIX((const char *) tmp, "ioemu:"))
|
2006-08-11 14:40:04 +00:00
|
|
|
tmp += 6;
|
2006-09-12 01:16:22 +00:00
|
|
|
|
|
|
|
/* Xend <= 3.0.2 wants a ioemu: prefix on devices for HVM */
|
|
|
|
if (xendConfigVersion == 1)
|
2007-10-24 14:22:25 +00:00
|
|
|
virBufferVSprintf(buf, "(dev 'ioemu:%s')", (const char *) tmp);
|
|
|
|
else /* But newer does not */
|
|
|
|
virBufferVSprintf(buf, "(dev '%s%s')", (const char *) tmp,
|
|
|
|
cdrom ? ":cdrom" : ":disk");
|
2006-08-11 14:40:04 +00:00
|
|
|
} else
|
2007-10-24 14:22:25 +00:00
|
|
|
virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
|
2006-10-09 14:32:07 +00:00
|
|
|
|
2007-04-11 16:06:30 +00:00
|
|
|
if (drvName && !isNoSrcCdrom) {
|
2008-05-14 19:51:24 +00:00
|
|
|
if (STREQ((const char *) drvName, "tap")) {
|
2006-10-09 14:32:07 +00:00
|
|
|
virBufferVSprintf(buf, "(uname '%s:%s:%s')",
|
2007-10-24 14:22:25 +00:00
|
|
|
(const char *) drvName,
|
|
|
|
(drvType ? (const char *) drvType : "aio"),
|
|
|
|
(const char *) source);
|
2006-10-09 14:32:07 +00:00
|
|
|
} else {
|
|
|
|
virBufferVSprintf(buf, "(uname '%s:%s')",
|
2007-10-24 14:22:25 +00:00
|
|
|
(const char *) drvName,
|
|
|
|
(const char *) source);
|
2006-10-09 14:32:07 +00:00
|
|
|
}
|
2007-04-11 16:06:30 +00:00
|
|
|
} else if (!isNoSrcCdrom) {
|
2006-10-09 14:32:07 +00:00
|
|
|
if (typ == 0)
|
|
|
|
virBufferVSprintf(buf, "(uname 'file:%s')", source);
|
|
|
|
else if (typ == 1) {
|
|
|
|
if (source[0] == '/')
|
|
|
|
virBufferVSprintf(buf, "(uname 'phy:%s')", source);
|
|
|
|
else
|
|
|
|
virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", source);
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2006-11-13 17:09:31 +00:00
|
|
|
if (ro == 1)
|
2008-02-20 15:29:13 +00:00
|
|
|
virBufferAddLit(buf, "(mode 'r')");
|
2006-11-13 17:09:31 +00:00
|
|
|
else if (shareable == 1)
|
2008-02-20 15:29:13 +00:00
|
|
|
virBufferAddLit(buf, "(mode 'w!')");
|
2006-11-13 17:09:31 +00:00
|
|
|
else
|
2008-02-20 15:29:13 +00:00
|
|
|
virBufferAddLit(buf, "(mode 'w')");
|
2006-02-16 22:50:52 +00:00
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, ")");
|
|
|
|
virBufferAddLit(buf, ")");
|
2006-10-06 15:32:48 +00:00
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
cleanup:
|
2008-04-29 19:43:57 +00:00
|
|
|
xmlFree(drvType);
|
|
|
|
xmlFree(drvName);
|
|
|
|
xmlFree(device);
|
|
|
|
xmlFree(target);
|
|
|
|
xmlFree(source);
|
2007-07-11 08:41:11 +00:00
|
|
|
return (ret);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainParseXMLIfDesc:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-07-10 11:21:24 +00:00
|
|
|
* @node: node containing the interface description
|
2006-02-16 22:50:52 +00:00
|
|
|
* @buf: a buffer for the result S-Expr
|
2007-06-06 14:39:04 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2006-02-16 22:50:52 +00:00
|
|
|
*
|
|
|
|
* Parse the one interface the XML description and add it to the S-Expr in buf
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static int
|
2007-10-24 14:22:25 +00:00
|
|
|
virDomainParseXMLIfDesc(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|
|
|
xmlNodePtr node, virBufferPtr buf, int hvm,
|
|
|
|
int xendConfigVersion)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlNodePtr cur;
|
|
|
|
xmlChar *type = NULL;
|
|
|
|
xmlChar *source = NULL;
|
|
|
|
xmlChar *mac = NULL;
|
|
|
|
xmlChar *script = NULL;
|
2008-04-30 12:30:55 +00:00
|
|
|
xmlChar *model = NULL;
|
2006-11-15 00:38:13 +00:00
|
|
|
xmlChar *ip = NULL;
|
2006-02-16 22:50:52 +00:00
|
|
|
int typ = 0;
|
2007-02-14 16:22:02 +00:00
|
|
|
int ret = -1;
|
2006-02-16 22:50:52 +00:00
|
|
|
|
|
|
|
type = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (type != NULL) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (xmlStrEqual(type, BAD_CAST "bridge"))
|
|
|
|
typ = 0;
|
|
|
|
else if (xmlStrEqual(type, BAD_CAST "ethernet"))
|
|
|
|
typ = 1;
|
2007-02-14 16:22:02 +00:00
|
|
|
else if (xmlStrEqual(type, BAD_CAST "network"))
|
|
|
|
typ = 2;
|
2006-03-15 12:13:25 +00:00
|
|
|
xmlFree(type);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if ((source == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
|
|
|
|
if (typ == 0)
|
|
|
|
source = xmlGetProp(cur, BAD_CAST "bridge");
|
2007-02-14 16:22:02 +00:00
|
|
|
else if (typ == 1)
|
2006-03-15 12:13:25 +00:00
|
|
|
source = xmlGetProp(cur, BAD_CAST "dev");
|
2007-02-14 16:22:02 +00:00
|
|
|
else
|
|
|
|
source = xmlGetProp(cur, BAD_CAST "network");
|
2006-03-15 12:13:25 +00:00
|
|
|
} else if ((mac == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "mac"))) {
|
|
|
|
mac = xmlGetProp(cur, BAD_CAST "address");
|
|
|
|
} else if ((script == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "script"))) {
|
|
|
|
script = xmlGetProp(cur, BAD_CAST "path");
|
2008-04-30 12:30:55 +00:00
|
|
|
} else if ((model == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "model"))) {
|
|
|
|
model = xmlGetProp(cur, BAD_CAST "type");
|
2006-11-15 00:38:13 +00:00
|
|
|
} else if ((ip == NULL) &&
|
|
|
|
(xmlStrEqual(cur->name, BAD_CAST "ip"))) {
|
|
|
|
/* XXX in future expect to need to have > 1 ip
|
2007-10-24 14:22:25 +00:00
|
|
|
* address element - eg ipv4 & ipv6. For now
|
|
|
|
* xen only supports a single address though
|
|
|
|
* so lets ignore that complication */
|
2006-11-15 00:38:13 +00:00
|
|
|
ip = xmlGetProp(cur, BAD_CAST "address");
|
2006-03-15 12:13:25 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(vif ");
|
2007-07-13 08:26:57 +00:00
|
|
|
if (mac != NULL) {
|
2008-03-20 11:24:30 +00:00
|
|
|
unsigned char addr[6];
|
|
|
|
if (virParseMacAddr((const char*) mac, addr) == -1) {
|
2007-07-13 08:26:57 +00:00
|
|
|
virXMLError(conn, VIR_ERR_INVALID_MAC, (const char *) mac, 0);
|
|
|
|
goto error;
|
|
|
|
}
|
2006-03-15 12:13:25 +00:00
|
|
|
virBufferVSprintf(buf, "(mac '%s')", (const char *) mac);
|
2007-07-13 08:26:57 +00:00
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
if (source != NULL) {
|
2006-03-15 12:13:25 +00:00
|
|
|
if (typ == 0)
|
|
|
|
virBufferVSprintf(buf, "(bridge '%s')", (const char *) source);
|
2007-02-14 16:22:02 +00:00
|
|
|
else if (typ == 1) /* TODO does that work like that ? */
|
2006-03-15 12:13:25 +00:00
|
|
|
virBufferVSprintf(buf, "(dev '%s')", (const char *) source);
|
2007-02-14 16:22:02 +00:00
|
|
|
else {
|
2007-10-24 14:22:25 +00:00
|
|
|
virNetworkPtr network =
|
|
|
|
virNetworkLookupByName(conn, (const char *) source);
|
2007-02-14 16:22:02 +00:00
|
|
|
char *bridge;
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2007-02-14 16:22:02 +00:00
|
|
|
if (!network || !(bridge = virNetworkGetBridgeName(network))) {
|
2007-10-10 17:41:06 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkFree(network);
|
2007-10-24 14:22:25 +00:00
|
|
|
virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) source,
|
|
|
|
0);
|
2007-02-14 16:22:02 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-10-10 17:41:06 +00:00
|
|
|
virNetworkFree(network);
|
2007-02-14 16:22:02 +00:00
|
|
|
virBufferVSprintf(buf, "(bridge '%s')", bridge);
|
|
|
|
free(bridge);
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
if (script != NULL)
|
|
|
|
virBufferVSprintf(buf, "(script '%s')", script);
|
2008-04-30 12:30:55 +00:00
|
|
|
if (model != NULL)
|
|
|
|
virBufferVSprintf(buf, "(model '%s')", model);
|
2006-11-15 00:38:13 +00:00
|
|
|
if (ip != NULL)
|
|
|
|
virBufferVSprintf(buf, "(ip '%s')", ip);
|
2007-06-06 14:39:04 +00:00
|
|
|
/*
|
|
|
|
* apparently (type ioemu) breaks paravirt drivers on HVM so skip this
|
|
|
|
* from Xen 3.1.0
|
|
|
|
*/
|
|
|
|
if ((hvm) && (xendConfigVersion < 4))
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, "(type ioemu)");
|
2006-02-16 22:50:52 +00:00
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(buf, ")");
|
2007-02-14 16:22:02 +00:00
|
|
|
ret = 0;
|
2007-10-24 14:22:25 +00:00
|
|
|
error:
|
2008-04-29 19:43:57 +00:00
|
|
|
xmlFree(mac);
|
|
|
|
xmlFree(source);
|
|
|
|
xmlFree(script);
|
|
|
|
xmlFree(ip);
|
2008-04-30 12:30:55 +00:00
|
|
|
xmlFree(model);
|
2007-02-14 16:22:02 +00:00
|
|
|
return (ret);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virDomainParseXMLDesc:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-02-16 22:50:52 +00:00
|
|
|
* @xmldesc: string with the XML description
|
2006-09-12 01:16:22 +00:00
|
|
|
* @xendConfigVersion: xend configuration file format
|
2006-02-16 22:50:52 +00:00
|
|
|
*
|
|
|
|
* Parse the XML description and turn it into the xend sexp needed to
|
2008-04-04 07:58:29 +00:00
|
|
|
* create the domain. This is a temporary interface as the S-Expr interface
|
2006-02-16 22:50:52 +00:00
|
|
|
* will be replaced by XML-RPC in the future. However the XML format should
|
|
|
|
* stay valid over time.
|
|
|
|
*
|
|
|
|
* Returns the 0 terminatedi S-Expr string or NULL in case of error.
|
|
|
|
* the caller must free() the returned value.
|
|
|
|
*/
|
|
|
|
char *
|
2007-10-24 14:22:25 +00:00
|
|
|
virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name,
|
|
|
|
int xendConfigVersion)
|
2006-03-15 12:13:25 +00:00
|
|
|
{
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlDocPtr xml = NULL;
|
|
|
|
xmlNodePtr node;
|
2007-04-23 07:41:23 +00:00
|
|
|
char *nam = NULL;
|
2008-04-28 15:14:59 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlChar *prop;
|
2006-11-08 16:55:20 +00:00
|
|
|
xmlParserCtxtPtr pctxt;
|
2006-02-16 22:50:52 +00:00
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
int i, res;
|
2006-03-30 16:08:13 +00:00
|
|
|
int bootloader = 0;
|
2006-08-11 14:40:04 +00:00
|
|
|
int hvm = 0;
|
2007-02-07 13:44:22 +00:00
|
|
|
unsigned int vcpus = 1;
|
2006-11-10 11:13:01 +00:00
|
|
|
unsigned long mem = 0, max_mem = 0;
|
2007-04-06 12:28:24 +00:00
|
|
|
char *str;
|
|
|
|
double f;
|
|
|
|
xmlNodePtr *nodes;
|
|
|
|
int nb_nodes;
|
2006-02-16 22:50:52 +00:00
|
|
|
|
|
|
|
if (name != NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
*name = NULL;
|
2006-02-16 22:50:52 +00:00
|
|
|
|
2006-11-08 16:55:20 +00:00
|
|
|
pctxt = xmlNewParserCtxt();
|
|
|
|
if ((pctxt == NULL) || (pctxt->sax == NULL)) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2007-02-14 16:16:13 +00:00
|
|
|
/* TODO pass the connection point to the error handler:
|
|
|
|
* pctxt->userData = virConnectPtr;
|
|
|
|
*/
|
2006-11-08 16:55:20 +00:00
|
|
|
pctxt->sax->error = virCatchXMLParseError;
|
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
xml = xmlCtxtReadDoc(pctxt, (const xmlChar *) xmldesc, "domain.xml",
|
|
|
|
NULL, XML_PARSE_NOENT | XML_PARSE_NONET |
|
2006-11-08 16:55:20 +00:00
|
|
|
XML_PARSE_NOWARNING);
|
2006-02-16 22:50:52 +00:00
|
|
|
if (xml == NULL) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
node = xmlDocGetRootElement(xml);
|
|
|
|
if ((node == NULL) || (!xmlStrEqual(node->name, BAD_CAST "domain")))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
prop = xmlGetProp(node, BAD_CAST "type");
|
|
|
|
if (prop != NULL) {
|
|
|
|
if (!xmlStrEqual(prop, BAD_CAST "xen")) {
|
2006-03-15 12:13:25 +00:00
|
|
|
xmlFree(prop);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
xmlFree(prop);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(&buf, "(vm ");
|
2006-02-16 22:50:52 +00:00
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
/*
|
2006-07-10 11:21:24 +00:00
|
|
|
* extract some of the basics, name, memory, cpus ...
|
2006-02-16 22:50:52 +00:00
|
|
|
*/
|
2007-04-06 12:28:24 +00:00
|
|
|
nam = virXPathString("string(/domain/name[1])", ctxt);
|
2006-02-27 22:32:54 +00:00
|
|
|
if (nam == NULL) {
|
2007-04-06 12:28:24 +00:00
|
|
|
virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
|
2006-03-15 12:13:25 +00:00
|
|
|
goto error;
|
2006-02-27 22:32:54 +00:00
|
|
|
}
|
2007-04-06 12:28:24 +00:00
|
|
|
virBufferVSprintf(&buf, "(name '%s')", nam);
|
2006-02-16 22:50:52 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
|
|
|
|
(f < MIN_XEN_GUEST_SIZE * 1024)) {
|
2007-02-07 13:50:18 +00:00
|
|
|
max_mem = 128;
|
2006-02-16 22:50:52 +00:00
|
|
|
} else {
|
2007-04-06 12:28:24 +00:00
|
|
|
max_mem = (f / 1024);
|
2006-11-10 11:13:01 +00:00
|
|
|
}
|
2007-04-06 12:28:24 +00:00
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0)
|
|
|
|
|| (f < MIN_XEN_GUEST_SIZE * 1024)) {
|
2006-11-10 11:13:01 +00:00
|
|
|
mem = max_mem;
|
|
|
|
} else {
|
2007-04-06 12:28:24 +00:00
|
|
|
mem = (f / 1024);
|
2007-02-07 13:50:18 +00:00
|
|
|
if (mem > max_mem) {
|
|
|
|
max_mem = mem;
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2006-11-10 11:13:01 +00:00
|
|
|
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
|
2006-02-16 22:50:52 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
|
|
|
|
(f > 0)) {
|
|
|
|
vcpus = (unsigned int) f;
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2007-02-07 13:44:22 +00:00
|
|
|
virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
|
2006-02-16 22:50:52 +00:00
|
|
|
|
2007-10-22 20:28:55 +00:00
|
|
|
str = virXPathString("string(/domain/vcpu/@cpuset)", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
int maxcpu = xenNbCpus(conn);
|
2007-10-24 14:22:25 +00:00
|
|
|
char *cpuset = NULL;
|
|
|
|
char *ranges = NULL;
|
|
|
|
const char *cur = str;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the CPUset attribute given in libvirt format and reserialize
|
|
|
|
* it in a range format guaranteed to be understood by Xen.
|
|
|
|
*/
|
|
|
|
if (maxcpu > 0) {
|
2007-12-11 21:57:29 +00:00
|
|
|
cpuset = malloc(maxcpu * sizeof(*cpuset));
|
2007-10-24 14:22:25 +00:00
|
|
|
if (cpuset != NULL) {
|
|
|
|
res = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
|
|
|
|
if (res > 0) {
|
2007-10-31 09:39:13 +00:00
|
|
|
ranges = virSaveCpuSet(conn, cpuset, maxcpu);
|
2007-10-24 14:22:25 +00:00
|
|
|
if (ranges != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(cpus '%s')", ranges);
|
|
|
|
free(ranges);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(cpuset);
|
2008-02-05 19:27:37 +00:00
|
|
|
if (res < 0)
|
2007-11-05 10:14:42 +00:00
|
|
|
goto error;
|
2007-10-24 14:22:25 +00:00
|
|
|
} else {
|
|
|
|
virXMLError(conn, VIR_ERR_NO_MEMORY, xmldesc, 0);
|
|
|
|
}
|
|
|
|
}
|
2007-10-22 20:28:55 +00:00
|
|
|
free(str);
|
|
|
|
}
|
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
str = virXPathString("string(/domain/uuid[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(uuid '%s')", str);
|
2007-10-24 14:22:25 +00:00
|
|
|
free(str);
|
2006-07-13 22:27:31 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
str = virXPathString("string(/domain/bootloader[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(bootloader '%s')", str);
|
2007-02-07 13:50:18 +00:00
|
|
|
/*
|
2007-06-07 13:50:18 +00:00
|
|
|
* if using a bootloader, the kernel and initrd strings are not
|
2007-02-07 13:50:18 +00:00
|
|
|
* significant and should be discarded
|
|
|
|
*/
|
2007-06-07 13:50:18 +00:00
|
|
|
bootloader = 1;
|
2007-10-24 14:22:25 +00:00
|
|
|
free(str);
|
|
|
|
} else if (virXPathNumber("count(/domain/bootloader)", ctxt, &f) == 0
|
|
|
|
&& (f > 0)) {
|
2008-02-20 15:29:13 +00:00
|
|
|
virBufferAddLit(&buf, "(bootloader)");
|
2007-09-29 18:31:05 +00:00
|
|
|
/*
|
|
|
|
* if using a bootloader, the kernel and initrd strings are not
|
|
|
|
* significant and should be discarded
|
|
|
|
*/
|
2007-10-24 14:22:25 +00:00
|
|
|
bootloader = 1;
|
2007-06-07 13:50:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
str = virXPathString("string(/domain/bootloader_args[1])", ctxt);
|
|
|
|
if (str != NULL && bootloader) {
|
|
|
|
/*
|
|
|
|
* ignore the bootloader_args value unless a bootloader was specified
|
|
|
|
*/
|
|
|
|
virBufferVSprintf(&buf, "(bootloader_args '%s')", str);
|
2007-10-24 14:22:25 +00:00
|
|
|
free(str);
|
2006-03-30 16:08:13 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
|
2007-10-24 14:22:25 +00:00
|
|
|
free(str);
|
2006-04-10 08:32:34 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
str = virXPathString("string(/domain/on_reboot[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(on_reboot '%s')", str);
|
2007-10-24 14:22:25 +00:00
|
|
|
free(str);
|
2006-04-10 08:32:34 +00:00
|
|
|
}
|
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
str = virXPathString("string(/domain/on_crash[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(on_crash '%s')", str);
|
2007-10-24 14:22:25 +00:00
|
|
|
free(str);
|
2006-04-10 08:32:34 +00:00
|
|
|
}
|
|
|
|
|
2007-06-07 13:50:18 +00:00
|
|
|
if (!bootloader) {
|
2007-04-06 12:28:24 +00:00
|
|
|
if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) {
|
2008-02-05 16:21:25 +00:00
|
|
|
int has_kernel = 0;
|
|
|
|
|
2007-02-07 13:50:18 +00:00
|
|
|
/* Analyze of the os description, based on HVM or PV. */
|
2007-06-07 13:50:18 +00:00
|
|
|
str = virXPathString("string(/domain/os/type[1])", ctxt);
|
2008-02-05 16:21:25 +00:00
|
|
|
if ((str != NULL) && STREQ(str, "hvm"))
|
2007-02-07 13:50:18 +00:00
|
|
|
hvm = 1;
|
2008-02-05 16:21:25 +00:00
|
|
|
xmlFree(str);
|
|
|
|
str = NULL;
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2008-02-05 16:21:25 +00:00
|
|
|
if (hvm)
|
|
|
|
virBufferAddLit(&buf, "(image (hvm ");
|
|
|
|
else
|
|
|
|
virBufferAddLit(&buf, "(image (linux ");
|
|
|
|
|
|
|
|
if (virXPathBoolean("count(/domain/os/kernel) > 0", ctxt)) {
|
|
|
|
if (virDomainParseXMLOSDescKernel(conn, node,
|
|
|
|
&buf) != 0)
|
|
|
|
goto error;
|
|
|
|
has_kernel = 1;
|
|
|
|
}
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2008-02-05 16:21:25 +00:00
|
|
|
if (hvm &&
|
|
|
|
virDomainParseXMLOSDescHVM(conn, node,
|
|
|
|
&buf, ctxt, vcpus,
|
|
|
|
xendConfigVersion,
|
|
|
|
has_kernel) != 0)
|
2007-02-07 13:50:18 +00:00
|
|
|
goto error;
|
2008-02-05 16:21:25 +00:00
|
|
|
|
|
|
|
/* get the device emulation model */
|
|
|
|
str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
|
|
|
|
if (str != NULL) {
|
|
|
|
virBufferVSprintf(&buf, "(device_model '%s')", str);
|
|
|
|
xmlFree(str);
|
|
|
|
str = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PV graphics for xen <= 3.0.4, or HVM graphics for xen <= 3.1.0 */
|
|
|
|
if ((!hvm && xendConfigVersion < 3) ||
|
|
|
|
(hvm && xendConfigVersion < 4)) {
|
|
|
|
xmlNodePtr cur;
|
|
|
|
cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
|
|
|
|
if (cur != NULL &&
|
|
|
|
virDomainParseXMLGraphicsDescImage(conn, cur, &buf,
|
|
|
|
xendConfigVersion) != 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&buf, "))");
|
2007-06-07 13:50:18 +00:00
|
|
|
} else {
|
2007-02-14 16:16:13 +00:00
|
|
|
virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
|
2007-02-07 13:50:18 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* analyze of the devices */
|
2007-04-06 12:28:24 +00:00
|
|
|
nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
|
|
|
|
if (nb_nodes > 0) {
|
|
|
|
for (i = 0; i < nb_nodes; i++) {
|
|
|
|
res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
|
2007-10-24 14:22:25 +00:00
|
|
|
hvm, xendConfigVersion);
|
2007-02-07 13:50:18 +00:00
|
|
|
if (res != 0) {
|
2007-10-24 14:22:25 +00:00
|
|
|
free(nodes);
|
2007-02-07 13:50:18 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2007-04-13 00:43:57 +00:00
|
|
|
free(nodes);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2006-07-07 14:36:27 +00:00
|
|
|
|
2007-04-06 12:28:24 +00:00
|
|
|
nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes);
|
|
|
|
if (nb_nodes > 0) {
|
|
|
|
for (i = 0; i < nb_nodes; i++) {
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(&buf, "(device ");
|
2007-10-24 14:22:25 +00:00
|
|
|
res =
|
|
|
|
virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm,
|
|
|
|
xendConfigVersion);
|
2006-03-15 12:13:25 +00:00
|
|
|
if (res != 0) {
|
2007-10-24 14:22:25 +00:00
|
|
|
free(nodes);
|
2006-03-15 12:13:25 +00:00
|
|
|
goto error;
|
|
|
|
}
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(&buf, ")");
|
2006-03-15 12:13:25 +00:00
|
|
|
}
|
2007-04-13 00:43:57 +00:00
|
|
|
free(nodes);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
|
|
|
|
2007-04-13 00:43:57 +00:00
|
|
|
/* New style PV graphics config xen >= 3.0.4,
|
|
|
|
* or HVM graphics config xen >= 3.0.5 */
|
|
|
|
if ((xendConfigVersion >= 3 && !hvm) ||
|
|
|
|
(xendConfigVersion >= 4 && hvm)) {
|
2007-04-06 12:28:24 +00:00
|
|
|
nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes);
|
2007-04-13 00:43:57 +00:00
|
|
|
if (nb_nodes > 0) {
|
2007-04-06 12:28:24 +00:00
|
|
|
for (i = 0; i < nb_nodes; i++) {
|
|
|
|
res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
|
2006-12-13 14:08:51 +00:00
|
|
|
if (res != 0) {
|
2007-04-13 00:43:57 +00:00
|
|
|
free(nodes);
|
2006-12-13 14:08:51 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2007-04-13 00:43:57 +00:00
|
|
|
free(nodes);
|
2006-12-13 14:08:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-16 22:50:52 +00:00
|
|
|
|
Eliminate all uses of virBufferAdd with string literals.
* Makefile.maint (sc_prohibit_virBufferAdd_with_string_literal):
New rule.
* src/buf.h (virBufferAddLit): Define.
* src/conf.c (virConfSaveValue): Use virBufferAddLit, in place
of virBufferAdd everywhere possible.
(virConfSaveEntry): Likewise.
* src/qemu_conf.c (qemudGenerateXML, qemudGenerateNetworkXML): Likewise.
* src/qemu_driver.c (qemudGetFeatures, qemudGetCapabilities): Likewise.
* src/test.c (testDomainDumpXML, testNetworkDumpXML): Likewise.
* src/xen_internal.c (xenHypervisorMakeCapabilitiesXML): Likewise.
* src/xend_internal.c (xend_parse_sexp_desc_os): Likewise.
(xend_parse_sexp_desc, sexpr_to_xend_topology_xml): Likewise.
* src/xm_internal.c (xenXMDomainFormatXML, xenXMDomainPinVcpu): Likewise.
* src/xml.c (virSaveCpuSet, virParseXenCpuTopology): Likewise.
(virDomainParseXMLGraphicsDescImage): Likewise.
(virDomainParseXMLGraphicsDescVFB, virDomainParseXMLOSDescHVM): Likewise.
(virDomainParseXMLOSDescPV, virDomainParseXMLDiskDesc): Likewise.
(virDomainParseXMLIfDesc, virDomainParseXMLDesc): Likewise.
2008-02-05 14:22:28 +00:00
|
|
|
virBufferAddLit(&buf, ")"); /* closes (vm */
|
2006-02-16 22:50:52 +00:00
|
|
|
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
xmlFreeDoc(xml);
|
2006-11-10 23:46:12 +00:00
|
|
|
xmlFreeParserCtxt(pctxt);
|
2006-02-27 22:32:54 +00:00
|
|
|
|
|
|
|
if (name != NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
*name = nam;
|
2006-10-06 15:32:48 +00:00
|
|
|
else
|
|
|
|
free(nam);
|
2006-02-16 22:50:52 +00:00
|
|
|
|
2008-04-28 15:14:59 +00:00
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
2006-03-15 12:13:25 +00:00
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
error:
|
2008-01-29 17:41:07 +00:00
|
|
|
free(nam);
|
2006-02-27 22:32:54 +00:00
|
|
|
if (name != NULL)
|
2006-03-15 12:13:25 +00:00
|
|
|
*name = NULL;
|
2008-01-29 18:23:43 +00:00
|
|
|
xmlXPathFreeContext(ctxt);
|
2006-02-16 22:50:52 +00:00
|
|
|
if (xml != NULL)
|
|
|
|
xmlFreeDoc(xml);
|
2006-11-10 23:46:12 +00:00
|
|
|
if (pctxt != NULL)
|
|
|
|
xmlFreeParserCtxt(pctxt);
|
2008-04-28 15:14:59 +00:00
|
|
|
free(virBufferContentAndReset(&buf));
|
2006-03-15 12:13:25 +00:00
|
|
|
return (NULL);
|
2006-02-16 22:50:52 +00:00
|
|
|
}
|
2006-08-09 15:21:16 +00:00
|
|
|
|
2006-11-16 18:11:28 +00:00
|
|
|
/**
|
|
|
|
* virParseXMLDevice:
|
2007-02-14 16:16:13 +00:00
|
|
|
* @conn: pointer to the hypervisor connection
|
2006-11-16 18:11:28 +00:00
|
|
|
* @xmldesc: string with the XML description
|
|
|
|
* @hvm: 1 for fully virtualized guest, 0 for paravirtualized
|
|
|
|
* @xendConfigVersion: xend configuration file format
|
|
|
|
*
|
|
|
|
* Parse the XML description and turn it into the xend sexp needed to
|
|
|
|
* create the device. 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 the 0-terminated S-Expr string, or NULL in case of error.
|
|
|
|
* the caller must free() the returned value.
|
|
|
|
*/
|
|
|
|
char *
|
2007-10-24 14:22:25 +00:00
|
|
|
virParseXMLDevice(virConnectPtr conn, const char *xmldesc, int hvm,
|
|
|
|
int xendConfigVersion)
|
2006-11-16 18:11:28 +00:00
|
|
|
{
|
|
|
|
xmlDocPtr xml = NULL;
|
|
|
|
xmlNodePtr node;
|
2008-04-28 15:14:59 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2006-11-16 18:11:28 +00:00
|
|
|
|
2007-08-02 10:47:38 +00:00
|
|
|
xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL,
|
2006-11-16 18:11:28 +00:00
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
2007-08-02 10:47:38 +00:00
|
|
|
if (xml == NULL) {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
|
2006-11-16 18:11:28 +00:00
|
|
|
goto error;
|
2007-08-02 10:47:38 +00:00
|
|
|
}
|
2006-11-16 18:11:28 +00:00
|
|
|
node = xmlDocGetRootElement(xml);
|
|
|
|
if (node == NULL)
|
|
|
|
goto error;
|
|
|
|
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
2007-10-24 14:22:25 +00:00
|
|
|
if (virDomainParseXMLDiskDesc(conn, node, &buf, hvm,
|
2008-04-10 16:54:54 +00:00
|
|
|
xendConfigVersion) != 0)
|
2006-11-16 18:11:28 +00:00
|
|
|
goto error;
|
2007-10-24 14:22:25 +00:00
|
|
|
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
|
|
|
|
if (virDomainParseXMLIfDesc(conn, node, &buf, hvm,
|
2008-04-10 16:54:54 +00:00
|
|
|
xendConfigVersion) != 0)
|
2006-11-16 18:11:28 +00:00
|
|
|
goto error;
|
2007-07-13 12:26:11 +00:00
|
|
|
} else {
|
|
|
|
virXMLError(conn, VIR_ERR_XML_ERROR, (const char *) node->name, 0);
|
2007-10-24 14:22:25 +00:00
|
|
|
goto error;
|
2006-11-16 18:11:28 +00:00
|
|
|
}
|
2008-04-28 15:14:59 +00:00
|
|
|
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
|
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
|
2007-10-24 14:22:25 +00:00
|
|
|
error:
|
2008-04-28 15:14:59 +00:00
|
|
|
free(virBufferContentAndReset(&buf));
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
return NULL;
|
2006-11-16 18:11:28 +00:00
|
|
|
}
|
|
|
|
|
2007-11-30 22:51:54 +00:00
|
|
|
|
2006-11-16 18:11:28 +00:00
|
|
|
/**
|
|
|
|
* virDomainXMLDevID:
|
|
|
|
* @domain: pointer to domain object
|
|
|
|
* @xmldesc: string with the XML description
|
|
|
|
* @class: Xen device class "vbd" or "vif" (OUT)
|
|
|
|
* @ref: Xen device reference (OUT)
|
|
|
|
*
|
|
|
|
* Set class according to XML root, and:
|
|
|
|
* - if disk, copy in ref the target name from description
|
|
|
|
* - if network, get MAC address from description, scan XenStore and
|
|
|
|
* copy in ref the corresponding vif number.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success, -1 in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
2007-10-24 14:22:25 +00:00
|
|
|
virDomainXMLDevID(virDomainPtr domain, const char *xmldesc, char *class,
|
|
|
|
char *ref, int ref_len)
|
2006-11-16 18:11:28 +00:00
|
|
|
{
|
|
|
|
xmlDocPtr xml = NULL;
|
|
|
|
xmlNodePtr node, cur;
|
|
|
|
xmlChar *attr = NULL;
|
2007-10-24 14:22:25 +00:00
|
|
|
|
2006-11-20 16:42:16 +00:00
|
|
|
char *xref;
|
2006-11-17 00:10:51 +00:00
|
|
|
int ret = 0;
|
2006-11-16 18:11:28 +00:00
|
|
|
|
2007-08-02 10:47:38 +00:00
|
|
|
xml = xmlReadDoc((const xmlChar *) xmldesc, "device.xml", NULL,
|
2006-11-16 18:11:28 +00:00
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
|
|
|
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
2007-08-02 10:47:38 +00:00
|
|
|
if (xml == NULL) {
|
|
|
|
virXMLError(NULL, VIR_ERR_XML_ERROR, NULL, 0);
|
2006-11-16 18:11:28 +00:00
|
|
|
goto error;
|
2007-08-02 10:47:38 +00:00
|
|
|
}
|
2006-11-16 18:11:28 +00:00
|
|
|
node = xmlDocGetRootElement(xml);
|
|
|
|
if (node == NULL)
|
|
|
|
goto error;
|
|
|
|
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
|
|
|
strcpy(class, "vbd");
|
|
|
|
for (cur = node->children; cur != NULL; cur = cur->next) {
|
|
|
|
if ((cur->type != XML_ELEMENT_NODE) ||
|
2007-10-24 14:22:25 +00:00
|
|
|
(!xmlStrEqual(cur->name, BAD_CAST "target")))
|
|
|
|
continue;
|
2006-11-16 18:11:28 +00:00
|
|
|
attr = xmlGetProp(cur, BAD_CAST "dev");
|
|
|
|
if (attr == NULL)
|
|
|
|
goto error;
|
2007-11-06 11:49:01 +00:00
|
|
|
xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
|
|
|
|
(char *) attr);
|
|
|
|
if (xref != NULL) {
|
|
|
|
strncpy(ref, xref, ref_len);
|
|
|
|
free(xref);
|
|
|
|
ref[ref_len - 1] = '\0';
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/* hack to avoid the warning that domain is unused */
|
|
|
|
if (domain->id < 0)
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
goto error;
|
2006-11-16 18:11:28 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
|
2006-11-16 18:11:28 +00:00
|
|
|
strcpy(class, "vif");
|
|
|
|
for (cur = node->children; cur != NULL; cur = cur->next) {
|
|
|
|
if ((cur->type != XML_ELEMENT_NODE) ||
|
2007-10-24 14:22:25 +00:00
|
|
|
(!xmlStrEqual(cur->name, BAD_CAST "mac")))
|
|
|
|
continue;
|
2006-11-16 18:11:28 +00:00
|
|
|
attr = xmlGetProp(cur, BAD_CAST "address");
|
|
|
|
if (attr == NULL)
|
|
|
|
goto error;
|
|
|
|
|
2007-01-22 16:25:27 +00:00
|
|
|
xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
|
2007-02-07 13:50:18 +00:00
|
|
|
(char *) attr);
|
|
|
|
if (xref != NULL) {
|
2007-09-12 15:41:51 +00:00
|
|
|
strncpy(ref, xref, ref_len);
|
2007-02-07 13:50:18 +00:00
|
|
|
free(xref);
|
2007-09-12 15:41:51 +00:00
|
|
|
ref[ref_len - 1] = '\0';
|
2007-02-07 13:50:18 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2007-03-16 14:55:51 +00:00
|
|
|
/* hack to avoid the warning that domain is unused */
|
|
|
|
if (domain->id < 0)
|
2007-10-24 14:22:25 +00:00
|
|
|
ret = -1;
|
2007-02-07 13:50:18 +00:00
|
|
|
|
2006-11-16 18:11:28 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2007-08-02 10:47:38 +00:00
|
|
|
} else {
|
|
|
|
virXMLError(NULL, VIR_ERR_XML_ERROR, (const char *) node->name, 0);
|
2006-11-16 18:11:28 +00:00
|
|
|
}
|
2007-10-24 14:22:25 +00:00
|
|
|
error:
|
2006-11-16 18:11:28 +00:00
|
|
|
ret = -1;
|
2007-10-24 14:22:25 +00:00
|
|
|
cleanup:
|
2006-11-16 18:11:28 +00:00
|
|
|
if (xml != NULL)
|
|
|
|
xmlFreeDoc(xml);
|
2008-04-29 19:43:57 +00:00
|
|
|
xmlFree(attr);
|
2006-11-16 18:11:28 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2007-11-30 22:51:54 +00:00
|
|
|
#endif /* WITH_XEN */
|
2006-11-16 18:11:28 +00:00
|
|
|
#endif /* !PROXY */
|