* src/xend_internal.c src/xml.c: patches from Jim Fehlig for HVM

guests, plus XML format changes and merge from Mark McLoughlin
Daniel
This commit is contained in:
Daniel Veillard 2006-07-10 11:21:24 +00:00
parent 3ffac4a188
commit 3d90a9c86d
3 changed files with 259 additions and 40 deletions

View File

@ -1,9 +1,14 @@
Mon Jul 10 12:27:17 CEST 2006 Daniel Veillard <veillard@redhat.com>
* src/xend_internal.c src/xml.c: patches from Jim Fehlig for HVM
guests, plus XML format changes and merge from Mark McLoughlin
Fri Jul 7 09:47:14 EDT 2006 Daniel Berrange <berrange@redhat.com> Fri Jul 7 09:47:14 EDT 2006 Daniel Berrange <berrange@redhat.com>
* src/xend_internal.c: changed xenDaemonLookupByID to simply do * src/xend_internal.c: changed xenDaemonLookupByID to simply do
an sexpr GET on /xend/domain/[ID] instead of listing all names an sexpr GET on /xend/domain/[ID] instead of listing all names
and iterating over /xend/domain/[NAME]. Reduces the running time and iterating over /xend/domain/[NAME]. Reduces the running time
and number of GETs from O(n^2) to O(n). and number of GETs from O(n^2) to O(n).
* src/xend_internal.c: fixed xenDaemonOpen() to try both unix and * src/xend_internal.c: fixed xenDaemonOpen() to try both unix and
Wed Jul 5 17:11:32 IST 2006 Mark McLoughlin <markmc@redhat.com> Wed Jul 5 17:11:32 IST 2006 Mark McLoughlin <markmc@redhat.com>

View File

@ -1350,10 +1350,77 @@ xend_log(virConnectPtr xend, char *buffer, size_t n_buffer)
****** ******
*****************************************************************/ *****************************************************************/
#ifndef XEN_RO #ifndef XEN_RO
/**
* xend_parse_sexp_desc_os:
* @node: the root of the parsed S-Expression
* @buf: output buffer object
* @hvm: true or 1 if no contains HVM S-Expression
*
* Parse the xend sexp for description of os and append it to buf.
*
* Returns 0 in case of success and -1 in case of error
*/
static int
xend_parse_sexp_desc_os(struct sexpr *node, virBufferPtr buf, int hvm)
{
const char *tmp;
if (node == NULL || buf == NULL) {
return(-1);
}
virBufferAdd(buf, " <os>\n", 7);
if (hvm) {
virBufferVSprintf(buf, " <type>hvm</type>\n");
tmp = sexpr_node(node, "domain/image/hvm/kernel");
if (tmp == NULL) {
virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
"domain informations incomplete, missing kernel");
return(-1);
}
virBufferVSprintf(buf, " <loader>%s</loader>\n", tmp);
tmp = sexpr_node(node, "domain/image/hvm/boot");
if ((tmp != NULL) && (tmp[0] != 0)) {
// FIXME:
// Figure out how to map the 'a', 'b', 'c' nonsense to a
// device.
if (tmp[0] == 'a')
virBufferAdd(buf, " <boot dev='/dev/fd0'/>\n", 25 );
else if (tmp[0] == 'c')
// Don't know what to put here. Say the vm has been given 3
// disks - hda, hdb, hdc. How does one identify the boot disk?
virBufferAdd(buf, " <boot dev='hda'/>\n", 22 );
else if (strcmp(tmp, "d") == 0)
virBufferAdd(buf, " <boot dev='/dev/cdrom'/>\n", 24 );
}
} else {
virBufferVSprintf(buf, " <type>linux</type>\n");
tmp = sexpr_node(node, "domain/image/linux/kernel");
if (tmp == NULL) {
virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
"domain informations incomplete, missing kernel");
return(-1);
}
virBufferVSprintf(buf, " <kernel>%s</kernel>\n", tmp);
tmp = sexpr_node(node, "domain/image/linux/ramdisk");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(buf, " <initrd>%s</initrd>\n", tmp);
tmp = sexpr_node(node, "domain/image/linux/root");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(buf, " <root>%s</root>\n", tmp);
tmp = sexpr_node(node, "domain/image/linux/args");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(buf, " <cmdline>%s</cmdline>\n", tmp);
}
virBufferAdd(buf, " </os>\n", 8);
return(0);
}
/** /**
* xend_parse_sexp_desc: * xend_parse_sexp_desc:
* @root: the root of the parsed S-Expression * @root: the root of the parsed S-Expression
* @name: output name of the domain
* *
* Parse the xend sexp description and turn it into the XML format similar * Parse the xend sexp description and turn it into the XML format similar
* to the one unsed for creation. * to the one unsed for creation.
@ -1368,6 +1435,7 @@ xend_parse_sexp_desc(struct sexpr *root)
struct sexpr *cur, *node; struct sexpr *cur, *node;
const char *tmp; const char *tmp;
virBuffer buf; virBuffer buf;
int hvm;
if (root == NULL) { if (root == NULL) {
/* ERROR */ /* ERROR */
@ -1407,30 +1475,12 @@ xend_parse_sexp_desc(struct sexpr *root)
tmp = sexpr_node(root, "domain/bootloader"); tmp = sexpr_node(root, "domain/bootloader");
if (tmp != NULL) if (tmp != NULL)
virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", tmp); virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", tmp);
if (sexpr_lookup(root, "domain/image")) { if (sexpr_lookup(root, "domain/image")) {
tmp = sexpr_node(root, "domain/image/linux/kernel"); hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
if (tmp == NULL) { xend_parse_sexp_desc_os(root, &buf, hvm);
/*
* TODO: we will need some fallback here for other guest OSes
*/
virXendError(NULL, VIR_ERR_INTERNAL_ERROR,
"domain informations incomplete, missing kernel");
goto error;
}
virBufferAdd(&buf, " <os>\n", 7);
virBufferVSprintf(&buf, " <type>linux</type>\n");
virBufferVSprintf(&buf, " <kernel>%s</kernel>\n", tmp);
tmp = sexpr_node(root, "domain/image/linux/ramdisk");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(&buf, " <initrd>%s</initrd>\n", tmp);
tmp = sexpr_node(root, "domain/image/linux/root");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(&buf, " <root>%s</root>\n", tmp);
tmp = sexpr_node(root, "domain/image/linux/args");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(&buf, " <cmdline>%s</cmdline>\n", tmp);
virBufferAdd(&buf, " </os>\n", 8);
} }
virBufferVSprintf(&buf, " <memory>%d</memory>\n", virBufferVSprintf(&buf, " <memory>%d</memory>\n",
(int) (sexpr_u64(root, "domain/maxmem") << 10)); (int) (sexpr_u64(root, "domain/maxmem") << 10));
virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n",
@ -1446,6 +1496,12 @@ xend_parse_sexp_desc(struct sexpr *root)
virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", tmp); virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", tmp);
virBufferAdd(&buf, " <devices>\n", 12); virBufferAdd(&buf, " <devices>\n", 12);
/* in case of HVM we have devices emulation */
tmp = sexpr_node(root, "domain/image/hvm/device_model");
if ((tmp != NULL) && (tmp[0] != 0))
virBufferVSprintf(&buf, " <emulator>%s</emulator>\n", tmp);
for (cur = root; cur->kind == SEXPR_CONS; cur = cur->cdr) { for (cur = root; cur->kind == SEXPR_CONS; cur = cur->cdr) {
node = cur->car; node = cur->car;
if (sexpr_lookup(node, "device/vbd")) { if (sexpr_lookup(node, "device/vbd")) {
@ -1523,9 +1579,32 @@ xend_parse_sexp_desc(struct sexpr *root)
virBufferVSprintf(&buf, "<!-- Failed to parse vif: %s -->\n", virBufferVSprintf(&buf, "<!-- Failed to parse vif: %s -->\n",
serial); serial);
} }
}
}
if (hvm) {
/* Graphics device */
/* TODO:
* Support for some additional attributes for graphics device?
*/
tmp = sexpr_node(root, "domain/image/hvm/vnc");
if (tmp != NULL) {
if (tmp[0] == '1')
virBufferAdd(&buf, " <graphics type='vnc'/>\n", 27 );
} }
tmp = sexpr_node(root, "domain/image/hvm/sdl");
if (tmp != NULL) {
if (tmp[0] == '1')
virBufferAdd(&buf, " <graphics type='sdl'/>\n", 27 );
} }
/*
* TODO:
* Device for cdrom
*/
}
virBufferAdd(&buf, " </devices>\n", 13); virBufferAdd(&buf, " </devices>\n", 13);
virBufferAdd(&buf, "</domain>\n", 10); virBufferAdd(&buf, "</domain>\n", 10);

163
src/xml.c
View File

@ -563,19 +563,141 @@ virDomainGetXMLDesc(virDomainPtr domain, int flags)
#endif #endif
/** /**
* virDomainParseXMLOSDesc: * virDomainParseXMLOSDescHVM:
* @xmldesc: string with the XML description * @node: node containing HVM OS description
* @buf: a buffer for the result S-Expr * @buf: a buffer for the result S-Expr
* @ctxt: a path context representing the XML description
* *
* Parse the OS part of the XML description and add it to the S-Expr in buf * Parse the OS part of the XML description for an HVM domain and add it to
* This is a temporary interface as the S-Expr interface * 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 * will be replaced by XML-RPC in the future. However the XML format should
* stay valid over time. * stay valid over time.
* *
* Returns 0 in case of success, -1 in case of error. * Returns 0 in case of success, -1 in case of error.
*/ */
static int static int
virDomainParseXMLOSDesc(xmlNodePtr node, virBufferPtr buf) virDomainParseXMLOSDescHVM(xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt)
{
xmlXPathObjectPtr obj = NULL;
xmlNodePtr cur, txt;
const xmlChar *type = NULL;
const xmlChar *loader = NULL;
const xmlChar *dev_model = NULL;
const xmlChar *boot_dev = NULL;
xmlChar *graphics_type = NULL;
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) {
if ((type == NULL)
&& (xmlStrEqual(cur->name, BAD_CAST "type"))) {
txt = cur->children;
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
(txt->next == NULL))
type = txt->content;
} else if ((loader == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "loader"))) {
txt = cur->children;
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
(txt->next == NULL))
loader = txt->content;
} else if ((boot_dev == NULL) &&
(xmlStrEqual(cur->name, BAD_CAST "boot"))) {
boot_dev = xmlGetProp(cur, BAD_CAST "dev");
}
}
cur = cur->next;
}
if ((type == NULL) || (!xmlStrEqual(type, BAD_CAST "hvm"))) {
/* VIR_ERR_OS_TYPE */
virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
return (-1);
}
virBufferAdd(buf, "(image (hvm ", 12);
if (loader == NULL) {
virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
goto error;
} else {
virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
}
/* get the device emulation model */
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
virXMLError(VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
goto error;
}
virBufferVSprintf(buf, "(device_model '%s')",
(const char *) obj->stringval);
xmlXPathFreeObject(obj);
obj = NULL;
if (boot_dev) {
/* TODO:
* Have to figure out the naming used here.
*/
if (xmlStrEqual(type, BAD_CAST "hda")) {
virBufferVSprintf(buf, "(boot a)", (const char *) boot_dev);
} else if (xmlStrEqual(type, BAD_CAST "hdd")) {
virBufferVSprintf(buf, "(boot d)", (const char *) boot_dev);
} else {
/* Force hd[b|c] if boot_dev specified but not floppy or cdrom? */
virBufferVSprintf(buf, "(boot c)", (const char *) boot_dev);
}
}
/* TODO:
* Is a cdrom disk device specified?
* Kind of ugly since it is buried in the devices/diskk node.
*/
/* Is a graphics device specified? */
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr = 0)) {
virXMLError(VIR_ERR_NO_OS, "", 0); /* TODO: error */
goto error;
}
graphics_type = xmlGetProp(obj->nodesetval->nodeTab[0], BAD_CAST "type");
if (graphics_type != NULL) {
if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
virBufferAdd(buf, "(sdl 1)", 7);
// TODO:
// Need to understand sdl options
//
//virBufferAdd(buf, "(display localhost:10.0)", 24);
//virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
}
else if (xmlStrEqual(graphics_type, BAD_CAST "vnc"))
virBufferAdd(buf, "(vnc 1)", 7);
xmlFree(graphics_type);
}
xmlXPathFreeObject(obj);
virBufferAdd(buf, "))", 2);
return (0);
error:
if (obj != NULL)
xmlXPathFreeObject(obj);
return(-1);
}
/**
* virDomainParseXMLOSDescPV:
* @node: node containing PV OS description
* @buf: a buffer for the result S-Expr
*
* Parse the OS part of the XML description for a paravirtualized domain
* 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
virDomainParseXMLOSDescPV(xmlNodePtr node, virBufferPtr buf)
{ {
xmlNodePtr cur, txt; xmlNodePtr cur, txt;
const xmlChar *type = NULL; const xmlChar *type = NULL;
@ -645,7 +767,7 @@ virDomainParseXMLOSDesc(xmlNodePtr node, virBufferPtr buf)
/** /**
* virDomainParseXMLDiskDesc: * virDomainParseXMLDiskDesc:
* @xmldesc: string with the XML description * @node: node containing disk description
* @buf: a buffer for the result S-Expr * @buf: a buffer for the result S-Expr
* *
* Parse the one disk in the XML description and add it to the S-Expr in buf * Parse the one disk in the XML description and add it to the S-Expr in buf
@ -707,10 +829,7 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf)
return (-1); return (-1);
} }
virBufferAdd(buf, "(vbd ", 5); virBufferAdd(buf, "(vbd ", 5);
if (target[0] == '/')
virBufferVSprintf(buf, "(dev '%s')", (const char *) target); virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
else
virBufferVSprintf(buf, "(dev '/dev/%s')", (const char *) target);
if (typ == 0) if (typ == 0)
virBufferVSprintf(buf, "(uname 'file:%s')", source); virBufferVSprintf(buf, "(uname 'file:%s')", source);
else if (typ == 1) { else if (typ == 1) {
@ -732,7 +851,7 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf)
/** /**
* virDomainParseXMLIfDesc: * virDomainParseXMLIfDesc:
* @xmldesc: string with the XML description * @node: node containing the interface description
* @buf: a buffer for the result S-Expr * @buf: a buffer for the result S-Expr
* *
* Parse the one interface the XML description and add it to the S-Expr in buf * Parse the one interface the XML description and add it to the S-Expr in buf
@ -824,6 +943,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name)
virBuffer buf; virBuffer buf;
xmlChar *prop; xmlChar *prop;
xmlXPathObjectPtr obj = NULL; xmlXPathObjectPtr obj = NULL;
xmlXPathObjectPtr tmpobj = NULL;
xmlXPathContextPtr ctxt = NULL; xmlXPathContextPtr ctxt = NULL;
int i, res; int i, res;
int bootloader = 0; int bootloader = 0;
@ -861,7 +981,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name)
goto error; goto error;
} }
/* /*
* extract soem of the basics, name, memory, cpus ... * extract some of the basics, name, memory, cpus ...
*/ */
obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt); obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) || if ((obj == NULL) || (obj->type != XPATH_STRING) ||
@ -928,14 +1048,29 @@ virDomainParseXMLDesc(const char *xmldesc, char **name)
} }
xmlXPathFreeObject(obj); xmlXPathFreeObject(obj);
/* analyze of the os description */
obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt); obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) && if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) { (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
res = virDomainParseXMLOSDesc(obj->nodesetval->nodeTab[0], &buf); /* Analyze of the os description, based on HVM or PV. */
if (res != 0) { tmpobj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
if ((tmpobj != NULL) &&
((tmpobj->type != XPATH_STRING) || (tmpobj->stringval == NULL) ||
(tmpobj->stringval[0] == 0))) {
xmlXPathFreeObject(tmpobj);
virXMLError(VIR_ERR_OS_TYPE, nam, 0);
goto error; goto error;
} }
if ((tmpobj == NULL) || !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) {
res = virDomainParseXMLOSDescPV(obj->nodesetval->nodeTab[0], &buf);
} else {
res = virDomainParseXMLOSDescHVM(obj->nodesetval->nodeTab[0], &buf, ctxt);
}
xmlXPathFreeObject(tmpobj);
if (res != 0)
goto error;
} else if (bootloader == 0) { } else if (bootloader == 0) {
virXMLError(VIR_ERR_NO_OS, nam, 0); virXMLError(VIR_ERR_NO_OS, nam, 0);
goto error; goto error;