Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.39
diff -u -r1.39 xend_internal.c
--- src/xend_internal.c	29 Jun 2006 23:53:31 -0000	1.39
+++ src/xend_internal.c	30 Jun 2006 22:08:55 -0000
@@ -1323,10 +1323,77 @@
  ******
  *****************************************************************/
 #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 nothing
+ */
+static void
+xend_parse_sexp_desc_os(struct sexpr *node, virBufferPtr buf, int hvm)
+{
+    const char *tmp;
+
+    if (node == NULL || buf == NULL) {
+       return;
+    }
+    
+    tmp = sexpr_node(node, hvm ? "domain/image/hvm/kernel" :
+                                 "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");
+        return;
+    }
+
+    virBufferAdd(buf, "  <os>\n", 7);
+    virBufferVSprintf(buf, hvm ? "    <type>hvm</type>\n" :
+                                 "    <type>linux</type>\n");
+    virBufferVSprintf(buf, "    <kernel>%s</kernel>\n", tmp);
+    if (hvm) {
+        tmp = sexpr_node(node, "domain/image/hvm/device_model");
+        if ((tmp != NULL) && (tmp[0] != 0))
+            virBufferVSprintf(buf, "    <device_model>%s</device_model>\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 {
+        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);
+}
+
 /**
  * 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.
@@ -1341,6 +1408,7 @@
     struct sexpr *cur, *node;
     const char *tmp;
     virBuffer buf;
+    int hvm;
 
     if (root == NULL) {
         /* ERROR */
@@ -1380,30 +1448,12 @@
     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",
@@ -1496,9 +1546,32 @@
                 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);
 
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.21
diff -u -r1.21 xml.c
--- src/xml.c	26 Jun 2006 15:02:19 -0000	1.21
+++ src/xml.c	30 Jun 2006 22:08:55 -0000
@@ -563,21 +563,146 @@
 #endif
 
 /**
- * virDomainParseXMLOSDesc:
- * @xmldesc: string with the XML description
+ * virDomainParseXMLDescHVM:
+ * @ctxt: a path context representing the XML description
  * @buf: a buffer for the result S-Expr
- * @bootloader: indocate if a bootloader script was provided
  *
- * 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, int bootloader)
+virDomainParseXMLDescHVM(xmlXPathContextPtr ctxt, virBufferPtr buf)
+{
+    xmlXPathObjectPtr obj = NULL;
+    xmlNodePtr cur, txt;
+    const xmlChar *type = NULL;
+    const xmlChar *kernel = NULL;
+    const xmlChar *dev_model = NULL;
+    const xmlChar *boot_dev = NULL;
+    xmlChar *graphics_type = NULL;
+
+    virBufferAdd(buf, "(image ", 7);
+    obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
+        virXMLError(VIR_ERR_NO_OS, "", 0);
+        return (-1);
+    }
+
+    cur = obj->nodesetval->nodeTab[0]->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE) {
+            if ((type == NULL)
+                && (xmlStrEqual(cur->name, BAD_CAST "type"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    type = txt->content;
+            } else if ((kernel == NULL) &&
+                       (xmlStrEqual(cur->name, BAD_CAST "kernel"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    kernel = txt->content;
+            } else if ((dev_model == NULL) &&
+                       (xmlStrEqual(cur->name, BAD_CAST "device_model"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    dev_model = 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, "(hvm ", 5);
+    if (kernel == NULL) {
+       virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
+       return (-1);
+    } else {
+       virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
+    }
+    if (dev_model == NULL) {
+       virXMLError(VIR_ERR_NO_KERNEL, NULL, 0); // need error
+       return (-1);
+    } else {
+       virBufferVSprintf(buf, "(device_model '%s')", (const char *) dev_model);
+    }
+    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);
+       }
+    }
+    xmlXPathFreeObject(obj);
+
+    /* 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 != 1)) {
+        virXMLError(VIR_ERR_NO_OS, "", 0); // need error
+        return (-1);
+    }
+
+    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, ")", 1); /* terminates (hvm */
+    virBufferAdd(buf, ")", 1); /* terminates (image */
+
+    return (0);
+}
+
+/**
+ * virDomainParseXMLDescPV:
+ * @ctxt: a path context representing the XML description
+ * @buf: a buffer for the result S-Expr
+ * @bootloader: indocate if a bootloader script was provided
+ *
+ * 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
+virDomainParseXMLDescPV(xmlXPathContextPtr ctxt, virBufferPtr buf, int bootloader)
 {
+    xmlXPathObjectPtr obj = NULL;
     xmlNodePtr cur, txt;
     const xmlChar *type = NULL;
     const xmlChar *root = NULL;
@@ -585,7 +710,15 @@
     const xmlChar *initrd = NULL;
     const xmlChar *cmdline = NULL;
 
-    cur = node->children;
+    virBufferAdd(buf, "(image ", 7);
+    obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
+        virXMLError(VIR_ERR_NO_OS, "", 0);
+        return (-1);
+    }
+
+    cur = obj->nodesetval->nodeTab[0]->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE) {
             if ((type == NULL)
@@ -617,19 +750,19 @@
         }
         cur = cur->next;
     }
-    if ((type != NULL) && (!xmlStrEqual(type, BAD_CAST "linux"))) {
+    if ((type == NULL) || (!xmlStrEqual(type, BAD_CAST "linux"))) {
         /* VIR_ERR_OS_TYPE */
         virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
         return (-1);
     }
     virBufferAdd(buf, "(linux ", 7);
     if (kernel == NULL) {
-	if (bootloader == 0) {
-	    virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
-	    return (-1);
-	}
+        if (bootloader == 0) {
+            virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
+            return (-1);
+        }
     } else {
-	virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
+        virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
     }
     if (initrd != NULL)
         virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
@@ -637,13 +770,21 @@
         virBufferVSprintf(buf, "(root '%s')", (const char *) root);
     if (cmdline != NULL)
         virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
-    virBufferAdd(buf, ")", 1);
+
+    /* TODO:
+     * Can this be freed earlier?
+     */
+    xmlXPathFreeObject(obj);
+
+    virBufferAdd(buf, ")", 1); /* terminates (linux */
+    virBufferAdd(buf, ")", 1); /* terminates (image */
+
     return (0);
 }
-
+    
 /**
  * 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
@@ -705,10 +846,7 @@
         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);
     if (typ == 0)
         virBufferVSprintf(buf, "(uname 'file:%s')", source);
     else if (typ == 1) {
@@ -730,7 +868,7 @@
 
 /**
  * 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
@@ -818,7 +956,7 @@
 {
     xmlDocPtr xml = NULL;
     xmlNodePtr node;
-    char *ret = NULL, *nam = NULL;
+    char *ret = NULL, *nam = NULL, *type = NULL;
     virBuffer buf;
     xmlChar *prop;
     xmlXPathObjectPtr obj = NULL;
@@ -859,7 +997,7 @@
         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) ||
@@ -909,7 +1047,6 @@
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 	virBufferVSprintf(&buf, "(on_poweroff '%s')", obj->stringval);
-	bootloader = 1;
     }
     xmlXPathFreeObject(obj);
 
@@ -917,7 +1054,6 @@
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 	virBufferVSprintf(&buf, "(on_reboot '%s')", obj->stringval);
-	bootloader = 1;
     }
     xmlXPathFreeObject(obj);
 
@@ -925,26 +1061,28 @@
     if ((obj != NULL) && (obj->type == XPATH_STRING) &&
         (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 	virBufferVSprintf(&buf, "(on_crash '%s')", obj->stringval);
-	bootloader = 1;
     }
     xmlXPathFreeObject(obj);
 
-    /* analyze of the os description */
-    virBufferAdd(&buf, "(image ", 7);
-    obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
-    if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
-        (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr != 1)) {
-        virXMLError(VIR_ERR_NO_OS, nam, 0);
+    /* Analyze of the os description, based on HVM or PV. */
+    obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
+    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+        (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+        virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
         goto error;
     }
-    res = virDomainParseXMLOSDesc(obj->nodesetval->nodeTab[0], &buf,
-                                  bootloader);
+    if (xmlStrEqual(obj->stringval, BAD_CAST "hvm")) {
+        res = virDomainParseXMLDescHVM(ctxt, &buf);
+    }
+    else {
+        res = virDomainParseXMLDescPV(ctxt, &buf, bootloader);
+    }
+    
     if (res != 0) {
         goto error;
     }
     xmlXPathFreeObject(obj);
-    virBufferAdd(&buf, ")", 1);
-
+    
     /* analyze of the devices */
     obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
@@ -976,7 +1114,6 @@
     }
     xmlXPathFreeObject(obj);
 
-
     virBufferAdd(&buf, ")", 1); /* closes (vm */
     buf.content[buf.use] = 0;
 
