]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
* src/xend_internal.c src/xml.c: patches from Jim Fehlig for HVM
authorDaniel Veillard <veillard@redhat.com>
Mon, 10 Jul 2006 11:21:24 +0000 (11:21 +0000)
committerDaniel Veillard <veillard@redhat.com>
Mon, 10 Jul 2006 11:21:24 +0000 (11:21 +0000)
  guests, plus XML format changes and merge from Mark McLoughlin
Daniel

ChangeLog
src/xend_internal.c
src/xml.c

index 5020d7dd83853b7a74940ed4f5df94c1fc92b271..79cd78bdc3903e281077bfbee4bf080d01e6aa90 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
+
        * src/xend_internal.c: changed xenDaemonLookupByID to simply do
        an sexpr GET on /xend/domain/[ID] instead of listing all names
        and iterating over /xend/domain/[NAME]. Reduces the running time
        and number of GETs from O(n^2) to O(n).
-
        * src/xend_internal.c: fixed xenDaemonOpen() to try both unix and
 
 Wed Jul  5 17:11:32 IST 2006 Mark McLoughlin <markmc@redhat.com>
index e7aa3bf2a7fe9b8f21b51f2084c17b7d1c5f4198..6e9c32bf9dadae37eef54ba3c879fa7588a8b04e 100644 (file)
@@ -1350,10 +1350,77 @@ xend_log(virConnectPtr xend, char *buffer, size_t n_buffer)
  ******
  *****************************************************************/
 #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.
@@ -1368,6 +1435,7 @@ xend_parse_sexp_desc(struct sexpr *root)
     struct sexpr *cur, *node;
     const char *tmp;
     virBuffer buf;
+    int hvm;
 
     if (root == NULL) {
         /* ERROR */
@@ -1407,30 +1475,12 @@ xend_parse_sexp_desc(struct sexpr *root)
     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",
@@ -1446,6 +1496,12 @@ xend_parse_sexp_desc(struct sexpr *root)
        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")) {
@@ -1523,9 +1579,32 @@ xend_parse_sexp_desc(struct sexpr *root)
                 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 44ea2ee66d568ef158a8b592f67932757cfce123..b30c00d292ab3bcb76d4bfc4af2129daac279616 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -563,19 +563,141 @@ virDomainGetXMLDesc(virDomainPtr domain, int flags)
 #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;
@@ -645,7 +767,7 @@ virDomainParseXMLOSDesc(xmlNodePtr node, virBufferPtr buf)
 
 /**
  * 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
@@ -707,10 +829,7 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr 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) {
@@ -732,7 +851,7 @@ virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf)
 
 /**
  * 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
@@ -824,6 +943,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name)
     virBuffer buf;
     xmlChar *prop;
     xmlXPathObjectPtr obj = NULL;
+    xmlXPathObjectPtr tmpobj = NULL;
     xmlXPathContextPtr ctxt = NULL;
     int i, res;
     int bootloader = 0;
@@ -861,7 +981,7 @@ virDomainParseXMLDesc(const char *xmldesc, char **name)
         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) ||
@@ -928,14 +1048,29 @@ virDomainParseXMLDesc(const char *xmldesc, char **name)
     }
     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;