******
*****************************************************************/
#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:
* @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
* to the one unsed for creation.
struct sexpr *cur, *node;
const char *tmp;
virBuffer buf;
+ int hvm;
if (root == NULL) {
/* ERROR */
tmp = sexpr_node(root, "domain/bootloader");
if (tmp != NULL)
virBufferVSprintf(&buf, " <bootloader>%s</bootloader>\n", tmp);
+
if (sexpr_lookup(root, "domain/image")) {
- tmp = sexpr_node(root, "domain/image/linux/kernel");
- if (tmp == NULL) {
- /*
- * 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);
+ hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
+ xend_parse_sexp_desc_os(root, &buf, hvm);
}
+
virBufferVSprintf(&buf, " <memory>%d</memory>\n",
(int) (sexpr_u64(root, "domain/maxmem") << 10));
virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n",
virBufferVSprintf(&buf, " <on_crash>%s</on_crash>\n", tmp);
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) {
node = cur->car;
if (sexpr_lookup(node, "device/vbd")) {
virBufferVSprintf(&buf, "<!-- Failed to parse vif: %s -->\n",
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, "</domain>\n", 10);
#endif
/**
- * virDomainParseXMLOSDesc:
- * @xmldesc: string with the XML description
+ * virDomainParseXMLOSDescHVM:
+ * @node: node containing HVM OS description
* @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
- * This is a temporary interface as the S-Expr interface
+ * Parse the OS part of the XML description for an HVM 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
-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;
const xmlChar *type = NULL;
/**
* virDomainParseXMLDiskDesc:
- * @xmldesc: string with the XML description
+ * @node: node containing disk description
* @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
return (-1);
}
virBufferAdd(buf, "(vbd ", 5);
- if (target[0] == '/')
- virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
- else
- virBufferVSprintf(buf, "(dev '/dev/%s')", (const char *) target);
+ virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
if (typ == 0)
virBufferVSprintf(buf, "(uname 'file:%s')", source);
else if (typ == 1) {
/**
* virDomainParseXMLIfDesc:
- * @xmldesc: string with the XML description
+ * @node: node containing the interface description
* @buf: a buffer for the result S-Expr
*
* Parse the one interface the XML description and add it to the S-Expr in buf
virBuffer buf;
xmlChar *prop;
xmlXPathObjectPtr obj = NULL;
+ xmlXPathObjectPtr tmpobj = NULL;
xmlXPathContextPtr ctxt = NULL;
int i, res;
int bootloader = 0;
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);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
}
xmlXPathFreeObject(obj);
- /* analyze of the os description */
obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
- res = virDomainParseXMLOSDesc(obj->nodesetval->nodeTab[0], &buf);
- if (res != 0) {
+ /* Analyze of the os description, based on HVM or PV. */
+ 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;
}
+
+ 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) {
virXMLError(VIR_ERR_NO_OS, nam, 0);
goto error;