[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] support for hvm guests



Daniel,

FYI, I'm working on a patch to support hvm guests. Attached is the work thus far. Calling "virsh dumpxml some_hvm_guest" will (almost) correctly dump xml config info on hvm guests. Needs to handle "type=ioemu" component of VIF specification. Currently in the XML there is a type attribute for the interface element that specifies bridge, route, etc. How would you like to structure the interface element and its children to account for hvm guests?

Using "virsh create file" where file contains XML config for hvm guests may be close to working but I haven't tested it yet. There are several options that need to be added to the XML to support hvm guests. If we can agree on the structure I can add the functionality.

Regards,
Jim
Index: xend_internal.c
===================================================================
RCS file: /data/cvs/libvir/src/xend_internal.c,v
retrieving revision 1.20
diff -u -r1.20 xend_internal.c
--- xend_internal.c	3 Apr 2006 13:46:43 -0000	1.20
+++ xend_internal.c	7 Apr 2006 22:20:03 -0000
@@ -1332,6 +1332,63 @@
  ******
  ******
  *****************************************************************/
+
+/**
+ * xend_parse_sexp_desc_os:
+ * @root: the root of the parsed S-Expression
+ * @buf: output buffer object
+ *
+ * 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)
+{
+    const char *tmp;
+    int hvm;
+
+    if (node == NULL || buf == NULL) {
+       return;
+    }
+    
+    hvm = sexpr_lookup(node, "domain/image/hvm") ? 1 : 0;
+    printf("hvm = %d\n", hvm);
+    
+    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);
+    }
+    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
@@ -1374,32 +1431,23 @@
     tmp = sexpr_node(root, "domain/bootloader");
     if (tmp != NULL)
 	virBufferVSprintf(&buf, "  <bootloader>%s</bootloader>\n", tmp);
-    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);
+
+    xend_parse_sexp_desc_os(root, &buf);
+
     virBufferVSprintf(&buf, "  <memory>%d</memory>\n",
                       (int) (sexpr_u64(root, "domain/maxmem") << 10));
     virBufferVSprintf(&buf, "  <vcpu>%d</vcpu>\n",
                       sexpr_int(root, "domain/vcpus"));
+    tmp = sexpr_node(root, "domain/on_poweroff");
+    if (tmp != NULL)
+	virBufferVSprintf(&buf, "  <on_poweroff>%s</on_poweroff>\n", tmp);
+    tmp = sexpr_node(root, "domain/on_reboot");
+    if (tmp != NULL)
+	virBufferVSprintf(&buf, "  <on_reboot>%s</on_reboot>\n", tmp);
+    tmp = sexpr_node(root, "domain/on_crash");
+    if (tmp != NULL)
+	virBufferVSprintf(&buf, "  <on_crash>%s</on_crash>\n", tmp);
+
     virBufferAdd(&buf, "  <devices>\n", 12);
     for (cur = root; cur->kind == SEXPR_CONS; cur = cur->cdr) {
         node = cur->car;
Index: xml.c
===================================================================
RCS file: /data/cvs/libvir/src/xml.c,v
retrieving revision 1.14
diff -u -r1.14 xml.c
--- xml.c	30 Mar 2006 16:08:13 -0000	1.14
+++ xml.c	7 Apr 2006 22:20:03 -0000
@@ -520,6 +520,8 @@
     const xmlChar *kernel = NULL;
     const xmlChar *initrd = NULL;
     const xmlChar *cmdline = NULL;
+    const xmlChar *dev_model = NULL;
+    const xmlChar *boot = NULL;
 
     cur = node->children;
     while (cur != NULL) {
@@ -549,65 +551,99 @@
                 txt = cur->children;
                 if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
                     cmdline = 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 == NULL) &&
+                       (xmlStrEqual(cur->name, BAD_CAST "boot"))) {
+                txt = cur->children;
+                if ((txt->type == XML_TEXT_NODE) && (txt->next == NULL))
+                    boot = txt->content;
             }
         }
         cur = cur->next;
     }
-    if ((type != NULL) && (!xmlStrEqual(type, BAD_CAST "linux"))) {
+    if ((type != NULL) && ((!xmlStrEqual(type, BAD_CAST "linux")) ||
+                           (!xmlStrEqual(type, BAD_CAST "hvm")))) {
         /* 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);
-	}
-    } else {
-	virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
-    }
-    if (initrd != NULL)
-        virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
-    if (root == NULL) {
-        const xmlChar *base, *tmp;
-
-        /* need to extract root info from command line */
-        if (cmdline == NULL) {
-            virXMLError(VIR_ERR_NO_ROOT, (const char *) cmdline, 0);
-            return (-1);
-        }
-        base = cmdline;
-        while (*base != 0) {
-            if ((base[0] == 'r') && (base[1] == 'o') && (base[2] == 'o') &&
-                (base[3] == 't')) {
-                base += 4;
-                break;
+    if (xmlStrEqual(type, BAD_CAST "linux")) {
+        virBufferAdd(buf, "(linux ", 7);
+        if (kernel == NULL) {
+            if (bootloader == 0) {
+                virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
+                return (-1);
             }
-            base++;
+        } else {
+            virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
         }
-        while ((*base == ' ') || (*base == '\t'))
-            base++;
-        if (*base == '=') {
-            base++;
-            while ((*base == ' ') || (*base == '\t'))
+        if (initrd != NULL)
+            virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
+        if (root == NULL) {
+            const xmlChar *base, *tmp;
+
+            /* need to extract root info from command line */
+            if (cmdline == NULL) {
+                virXMLError(VIR_ERR_NO_ROOT, (const char *) cmdline, 0);
+                return (-1);
+            }
+            base = cmdline;
+            while (*base != 0) {
+                if ((base[0] == 'r') && (base[1] == 'o') && (base[2] == 'o') &&
+                    (base[3] == 't')) {
+                    base += 4;
+                    break;
+                }
                 base++;
+            }
+            while ((*base == ' ') || (*base == '\t'))
+               base++;
+            if (*base == '=') {
+               base++;
+               while ((*base == ' ') || (*base == '\t'))
+                  base++;
+            }
+            tmp = base;
+            while ((*tmp != 0) && (*tmp != ' ') && (*tmp != '\t'))
+               tmp++;
+            if (tmp == base) {
+               virXMLError(VIR_ERR_NO_ROOT, (const char *) cmdline, 0);
+               return (-1);
+            }
+            root = xmlStrndup(base, tmp - base);
+            virBufferVSprintf(buf, "(root '%s')", (const char *) root);
+            xmlFree((xmlChar *) root);
+            virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
+        } else {
+           virBufferVSprintf(buf, "(root '%s')", (const char *) root);
+           if (cmdline != NULL)
+              virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
         }
-        tmp = base;
-        while ((*tmp != 0) && (*tmp != ' ') && (*tmp != '\t'))
-            tmp++;
-        if (tmp == base) {
-            virXMLError(VIR_ERR_NO_ROOT, (const char *) cmdline, 0);
+    }
+    else {
+        virBufferAdd(buf, "(hvm ", 7);
+        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 == NULL) {
+            virXMLError(VIR_ERR_NO_KERNEL, NULL, 0); // need error
+            return (-1);
+        } else {
+            virBufferVSprintf(buf, "(boot '%s')", (const char *) boot);
         }
-        root = xmlStrndup(base, tmp - base);
-        virBufferVSprintf(buf, "(root '%s')", (const char *) root);
-        xmlFree((xmlChar *) root);
-        virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
-    } else {
-        virBufferVSprintf(buf, "(root '%s')", (const char *) root);
-        if (cmdline != NULL)
-            virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
     }
     virBufferAdd(buf, ")", 1);
     return (0);
@@ -877,6 +913,30 @@
     }
     xmlXPathFreeObject(obj);
 
+    obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt);
+    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);
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt);
+    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);
+
+    obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt);
+    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);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]