[Libvir] Fix handling of HVM boot parameters

Daniel P. Berrange berrange at redhat.com
Thu Aug 10 22:00:01 UTC 2006


On Thu, Aug 10, 2006 at 08:31:28AM -0400, Daniel Veillard wrote:
> On Wed, Aug 09, 2006 at 11:54:26PM +0100, Daniel P. Berrange wrote:
> [ lot of details about problems ]
> > The upshot of all this is that although the last release of libvirt
> > included HVM support it was basically unusable for domain creation
> > unless you were using HD to boot. The XML returned was also incorrect.
> > 
> > Now the good news. Since it was sooo broken, we can fix without worrying
> > about XML compatability since there is no way any application could be
> > relying on it in its current state.
> 
>   Agreed. And the changes suggested should not affect the very simple
> case which worked, except for the 'ioemu:' device prefix. We can just
> discard it when reading the XML and add it when 
> just discard it except that before xen-3.0.3 this will need to be added
> back, and post xen-3.0.3 this should be allowed by xend 

Ok attached an updated version of the patch which the various changes discussed
in this thread - in particular the addition of a 'device' attribute to the <disk>
element accepting 'disk', 'floppy', or 'cdrom' and defaulting to 'disk' if it
is omitted. Best illustrated by example XML dump:

<domain type='xen' id='53'>
  <name>too</name>
  <uuid>b5d70dd275cdaca517769660b059d8bc</uuid>
  <os>
    <type>hvm</type>
    <loader>/usr/lib/xen/boot/hvmloader</loader>
    <boot dev='cdrom'/>
  </os>
  <memory>409600</memory>
  <vcpu>1</vcpu>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
    <interface type='bridge'>
      <source bridge='xenbr0'/>
      <mac address='00:16:3e:1b:b1:47'/>
      <script path='vif-bridge'/>
    </interface>
    <disk type='file' device='disk'>
      <source file='/root/foo.img'/>
      <target dev='hda'/>
    </disk>
    <disk type='file' device='cdrom'>
      <source file='/root/boot.iso'/>
      <target dev='hdc'/>
      <readonly/>
    </disk>
    <graphics type='vnc' port='5953'/>
    <console tty='/dev/pts/16'/>
  </devices>
</domain>

Note that the ioemu: prefix is now not exposed in the XML - we add it back
on when creating the SEXPR, or strip it when parsing the SEXPR. Until Xen
3.0.3 when 'device=cdrom' the only valid target dev is 'hdc', after 3.0.3
this can be relaxed to allow hda->hdd

Regards,
Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
? COPYING
? build.log
Index: src/libvirt.c
===================================================================
RCS file: /data/cvs/libvirt/src/libvirt.c,v
retrieving revision 1.41
diff -c -b -r1.41 libvirt.c
*** src/libvirt.c	9 Aug 2006 15:21:16 -0000	1.41
--- src/libvirt.c	10 Aug 2006 22:38:56 -0000
***************
*** 720,726 ****
  int
  virDomainDestroy(virDomainPtr domain)
  {
!     int ret = -1, i;
      virConnectPtr conn;
  
      if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
--- 720,726 ----
  int
  virDomainDestroy(virDomainPtr domain)
  {
!     int i;
      virConnectPtr conn;
  
      if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
***************
*** 743,749 ****
  	    (conn->drivers[i]->no != VIR_DRV_XEN_HYPERVISOR) &&
  	    (conn->drivers[i]->domainDestroy != NULL)) {
  	    if (conn->drivers[i]->domainDestroy(domain) == 0)
! 	        ret = 0;
  	}
      }
      for (i = 0;i < conn->nb_drivers;i++) {
--- 743,749 ----
  	    (conn->drivers[i]->no != VIR_DRV_XEN_HYPERVISOR) &&
  	    (conn->drivers[i]->domainDestroy != NULL)) {
  	    if (conn->drivers[i]->domainDestroy(domain) == 0)
! 	        return (0);
  	}
      }
      for (i = 0;i < conn->nb_drivers;i++) {
***************
*** 751,766 ****
  	    (conn->drivers[i]->no == VIR_DRV_XEN_HYPERVISOR) &&
  	    (conn->drivers[i]->domainDestroy != NULL)) {
  	    if (conn->drivers[i]->domainDestroy(domain) == 0)
! 	        ret = 0;
  	}
      }
  
-     if (ret != 0) {
          virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
!         return (ret);
!     }
! 
!     return (ret);
  }
  
  /**
--- 751,762 ----
              (conn->drivers[i]->no == VIR_DRV_XEN_HYPERVISOR) &&
              (conn->drivers[i]->domainDestroy != NULL)) {
  	    if (conn->drivers[i]->domainDestroy(domain) == 0)
! 	        return (0);
          }
      }
  
      virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
!     return (-1);
  }
  
  /**
***************
*** 799,805 ****
  int
  virDomainSuspend(virDomainPtr domain)
  {
!     int ret = -1, i;
      virConnectPtr conn;
  
      if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
--- 795,801 ----
  int
  virDomainSuspend(virDomainPtr domain)
  {
!     int i;
      virConnectPtr conn;
  
      if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
***************
*** 822,828 ****
  	    (conn->drivers[i]->no != VIR_DRV_XEN_HYPERVISOR) &&
  	    (conn->drivers[i]->domainSuspend != NULL)) {
  	    if (conn->drivers[i]->domainSuspend(domain) == 0)
! 	        ret = 0;
  	}
      }
      for (i = 0;i < conn->nb_drivers;i++) {
--- 818,824 ----
  	    (conn->drivers[i]->no != VIR_DRV_XEN_HYPERVISOR) &&
  	    (conn->drivers[i]->domainSuspend != NULL)) {
  	    if (conn->drivers[i]->domainSuspend(domain) == 0)
! 	        return (0);
  	}
      }
      for (i = 0;i < conn->nb_drivers;i++) {
***************
*** 830,845 ****
  	    (conn->drivers[i]->no == VIR_DRV_XEN_HYPERVISOR) &&
  	    (conn->drivers[i]->domainSuspend != NULL)) {
  	    if (conn->drivers[i]->domainSuspend(domain) == 0)
! 	        ret = 0;
  	}
      }
  
-     if (ret != 0) {
          virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
!         return (ret);
!     }
! 
!     return (ret);
  }
  
  /**
--- 826,837 ----
  	    (conn->drivers[i]->no == VIR_DRV_XEN_HYPERVISOR) &&
              (conn->drivers[i]->domainSuspend != NULL)) {
  	    if (conn->drivers[i]->domainSuspend(domain) == 0)
! 	        return (0);
          }
      }
  
      virLibConnError(conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
!     return (-1);
  }
  
  /**
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.52
diff -c -b -r1.52 xend_internal.c
*** src/xend_internal.c	9 Aug 2006 15:21:16 -0000	1.52
--- src/xend_internal.c	10 Aug 2006 22:38:57 -0000
***************
*** 791,796 ****
--- 791,808 ----
          goto error;
  
      ret = sscanf(r,
+                  "%02x%02x%02x%02x"
+                  "%02x%02x%02x%02x"
+                  "%02x%02x%02x%02x"
+                  "%02x%02x%02x%02x",
+                  uuid + 0, uuid + 1, uuid + 2, uuid + 3,
+                  uuid + 4, uuid + 5, uuid + 6, uuid + 7,
+                  uuid + 8, uuid + 9, uuid + 10, uuid + 11,
+                  uuid + 12, uuid + 13, uuid + 14, uuid + 15);
+     if (ret == 16)
+         goto done;
+ 
+     ret = sscanf(r,
                   "%02x%02x%02x%02x-"
                   "%02x%02x-"
                   "%02x%02x-"
***************
*** 1416,1436 ****
          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", 29 );
          }
      } else {
          virBufferVSprintf(buf, "    <type>linux</type>\n");
--- 1428,1446 ----
          virBufferVSprintf(buf, "    <loader>%s</loader>\n", tmp);
          tmp = sexpr_node(node, "domain/image/hvm/boot");
          if ((tmp != NULL) && (tmp[0] != 0)) {
             if (tmp[0] == 'a')
!                /* XXX no way to deal with boot from 2nd floppy */
!                virBufferAdd(buf, "    <boot dev='fd'/>\n", 21 );
             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?
+                 * We're going to assume that first disk is the boot disk since
+                 * this is most common practice
                  */
!                virBufferAdd(buf, "    <boot dev='hd'/>\n", 21 );
             else if (strcmp(tmp, "d") == 0)
!                virBufferAdd(buf, "    <boot dev='cdrom'/>\n", 24 );
          }
      } else {
          virBufferVSprintf(buf, "    <type>linux</type>\n");
***************
*** 1482,1492 ****
          /* ERROR */
          return (NULL);
      }
!     ret = malloc(1000);
      if (ret == NULL)
          return (NULL);
      buf.content = ret;
!     buf.size = 1000;
      buf.use = 0;
  
      domid = sexpr_int(root, "domain/domid");
--- 1492,1502 ----
          /* ERROR */
          return (NULL);
      }
!     ret = malloc(4000);
      if (ret == NULL)
          return (NULL);
      buf.content = ret;
!     buf.size = 4000;
      buf.use = 0;
  
      domid = sexpr_int(root, "domain/domid");
***************
*** 1552,1558 ****
                  continue;
              if (!memcmp(tmp, "file:", 5)) {
                  tmp += 5;
!                 virBufferVSprintf(&buf, "    <disk type='file'>\n");
                  virBufferVSprintf(&buf, "      <source file='%s'/>\n",
                                    tmp);
                  tmp = sexpr_node(node, "device/vbd/dev");
--- 1562,1568 ----
                  continue;
              if (!memcmp(tmp, "file:", 5)) {
                  tmp += 5;
!                 virBufferVSprintf(&buf, "    <disk type='file' device='disk'>\n");
                  virBufferVSprintf(&buf, "      <source file='%s'/>\n",
                                    tmp);
                  tmp = sexpr_node(node, "device/vbd/dev");
***************
*** 1561,1566 ****
--- 1571,1578 ----
                                   "domain information incomplete, vbd has no dev");
                      goto error;
                  }
+                 if (!strncmp(tmp, "ioemu:", 6)) 
+                     tmp += 6;
                  virBufferVSprintf(&buf, "      <target dev='%s'/>\n", tmp);
                  tmp = sexpr_node(node, "device/vbd/mode");
                  if ((tmp != NULL) && (!strcmp(tmp, "r")))
***************
*** 1568,1574 ****
                  virBufferAdd(&buf, "    </disk>\n", 12);
              } else if (!memcmp(tmp, "phy:", 4)) {
                  tmp += 4;
!                 virBufferVSprintf(&buf, "    <disk type='block'>\n");
                  virBufferVSprintf(&buf, "      <source dev='%s'/>\n", tmp);
                  tmp = sexpr_node(node, "device/vbd/dev");
                  if (tmp == NULL) {
--- 1580,1586 ----
                  virBufferAdd(&buf, "    </disk>\n", 12);
              } else if (!memcmp(tmp, "phy:", 4)) {
                  tmp += 4;
!                 virBufferVSprintf(&buf, "    <disk type='block' device='disk'>\n");
                  virBufferVSprintf(&buf, "      <source dev='%s'/>\n", tmp);
                  tmp = sexpr_node(node, "device/vbd/dev");
                  if (tmp == NULL) {
***************
*** 1576,1581 ****
--- 1588,1595 ----
                                   "domain information incomplete, vbd has no dev");
                      goto error;
                  }
+                 if (!strncmp(tmp, "ioemu:", 6)) 
+                     tmp += 6;
                  virBufferVSprintf(&buf, "      <target dev='%s'/>\n", tmp);
                  tmp = sexpr_node(node, "device/vbd/mode");
                  if ((tmp != NULL) && (!strcmp(tmp, "r")))
***************
*** 1625,1630 ****
--- 1639,1668 ----
      }
  
      if (hvm) {
+         tmp = sexpr_node(root, "domain/image/hvm/fda");
+         if ((tmp != NULL) && (tmp[0] != 0)) {
+             virBufferAdd(&buf, "    <disk type='file' device='floppy'>\n", 39);
+             virBufferVSprintf(&buf, "      <source file='%s'/>\n", tmp);
+             virBufferAdd(&buf, "      <target dev='fda'/>\n", 26);
+             virBufferAdd(&buf, "    </disk>\n", 12);
+         }
+         tmp = sexpr_node(root, "domain/image/hvm/fdb");
+         if ((tmp != NULL) && (tmp[0] != 0)) {
+             virBufferAdd(&buf, "    <disk type='file' device='floppy'>\n", 39);
+             virBufferVSprintf(&buf, "      <source file='%s'/>\n", tmp);
+             virBufferAdd(&buf, "      <target dev='fdb'/>\n", 26);
+             virBufferAdd(&buf, "    </disk>\n", 12);
+         }
+         /* XXX new (3.0.3) Xend puts cdrom devs in usual (devices) block */
+         tmp = sexpr_node(root, "domain/image/hvm/cdrom");
+         if ((tmp != NULL) && (tmp[0] != 0)) {
+             virBufferAdd(&buf, "    <disk type='file' device='cdrom'>\n", 38);
+             virBufferVSprintf(&buf, "      <source file='%s'/>\n", tmp);
+             virBufferAdd(&buf, "      <target dev='hdc'/>\n", 26);
+             virBufferAdd(&buf, "      <readonly/>\n", 18);
+             virBufferAdd(&buf, "    </disk>\n", 12);
+         }
+         
          /* Graphics device */
          tmp = sexpr_node(root, "domain/image/hvm/vnc");
          if (tmp != NULL) {
***************
*** 1641,1651 ****
             if (tmp[0] == '1')
                 virBufferAdd(&buf, "    <graphics type='sdl'/>\n", 27 );
          }
- 
-         /*
-          * TODO:
-          * Device for cdrom
-          */
      }
      
      tty = xenStoreDomainGetConsolePath(conn, domid);
--- 1679,1684 ----
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.31
diff -c -b -r1.31 xml.c
*** src/xml.c	10 Aug 2006 14:26:35 -0000	1.31
--- src/xml.c	10 Aug 2006 22:38:58 -0000
***************
*** 268,274 ****
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
          if (val != NULL) {
!             virBufferVSprintf(buf, "      <target dev='%s'/>\n", val);
              free(val);
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
--- 268,277 ----
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
          if (val != NULL) {
!             char *tmp = val;
!             if (!strncmp(tmp, "ioemu:", 6))
!                 tmp += 6;
!             virBufferVSprintf(buf, "      <target dev='%s'/>\n", tmp);
              free(val);
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
***************
*** 286,292 ****
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
          if (val != NULL) {
!             virBufferVSprintf(buf, "      <target dev='%s'/>\n", val);
              free(val);
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
--- 289,298 ----
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
          if (val != NULL) {
!             char *tmp = val;
!             if (!strncmp(tmp, "ioemu:", 6))
!                 tmp += 6;
!             virBufferVSprintf(buf, "      <target dev='%s'/>\n", tmp);
              free(val);
          }
          val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
***************
*** 635,656 ****
      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);
--- 641,712 ----
      obj = NULL;
  
      if (boot_dev) {
!        if (xmlStrEqual(boot_dev, BAD_CAST "fd")) {
            virBufferVSprintf(buf, "(boot a)", (const char *) boot_dev);
!        } else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) {
            virBufferVSprintf(buf, "(boot d)", (const char *) boot_dev);
!        } else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) {
            virBufferVSprintf(buf, "(boot c)", (const char *) boot_dev);
+        } else {
+          /* Any other type of boot dev is unsupported right now */
+          virXMLError(VIR_ERR_XML_ERROR, NULL, 0);
         }
+ 
+        /* get the 1st floppy device file */
+        obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", ctxt);
+        if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
+            (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
+          cur = obj->nodesetval->nodeTab[0];
+          virBufferVSprintf(buf, "(fda '%s')",
+                            (const char *) xmlGetProp(cur, BAD_CAST "file"));
+          cur = NULL;
+        }
+        if (obj) {
+          xmlXPathFreeObject(obj);
+          obj = NULL;
         }
! 
!        /* get the 2nd floppy device file */
!        obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", ctxt);
!        if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
!            (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
!          cur = obj->nodesetval->nodeTab[0];
!          virBufferVSprintf(buf, "(fdb '%s')",
!                            (const char *) xmlGetProp(cur, BAD_CAST "file"));
!          cur = NULL;
!        }
!        if (obj) {
!          xmlXPathFreeObject(obj);
!          obj = NULL;
!        }
! 
! 
!        /* get the cdrom device file */
!        /* XXX new (3.0.3) Xend puts cdrom devs in usual (devices) block */
!        obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", ctxt);
!        if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
!            (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
!          cur = obj->nodesetval->nodeTab[0];
!          virBufferVSprintf(buf, "(cdrom '%s')",
!                            (const char *) xmlGetProp(cur, BAD_CAST "file"));
!          cur = NULL;
!        }
!        if (obj) {
!          xmlXPathFreeObject(obj);
!          obj = NULL;
!        }
!     }
! 
!     obj = xmlXPathEval(BAD_CAST "count(domain/devices/console) > 0", ctxt);
!     if ((obj == NULL) || (obj->type != XPATH_BOOLEAN)) {
!       virXMLError(VIR_ERR_XML_ERROR, NULL, 0);
!       goto error;
!     }
!     if (obj->boolval) {
!       virBufferAdd(buf, "(serial pty)", 12);
!     }
!     xmlXPathFreeObject(obj);
!     obj = NULL;
      
      /* Is a graphics device specified? */
      obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
***************
*** 779,788 ****
   * Returns 0 in case of success, -1 in case of error.
   */
  static int
! virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf)
  {
      xmlNodePtr cur;
      xmlChar *type = NULL;
      xmlChar *source = NULL;
      xmlChar *target = NULL;
      int ro = 0;
--- 835,845 ----
   * Returns 0 in case of success, -1 in case of error.
   */
  static int
! virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf, int hvm)
  {
      xmlNodePtr cur;
      xmlChar *type = NULL;
+     xmlChar *device = NULL;
      xmlChar *source = NULL;
      xmlChar *target = NULL;
      int ro = 0;
***************
*** 796,801 ****
--- 853,860 ----
              typ = 1;
          xmlFree(type);
      }
+     device = xmlGetProp(node, BAD_CAST "device");
+     
      cur = node->children;
      while (cur != NULL) {
          if (cur->type == XML_ELEMENT_NODE) {
***************
*** 829,835 ****
--- 888,914 ----
              xmlFree(source);
          return (-1);
      }
+ 
+     /* Skip floppy/cdrom disk used as the boot device
+        since that's incorporated into the HVM kernel
+        (image (hvm..)) part of the sexpr, rather than
+        the (devices...) bit. Odd Xend HVM config :-( */
+     if (hvm && device &&
+         (!strcmp((const char *)device, "floppy") ||
+          !strcmp((const char *)device, "cdrom"))) {
+       return 0;
+     }
+ 
+ 
+     virBufferAdd(buf, "(device ", 8);
      virBufferAdd(buf, "(vbd ", 5);
+     /* XXX ioemu prefix is going away in XenD 3.0.3 */
+     if (hvm) {
+         char *tmp = (char *)target;
+         if (!strncmp((const char *) tmp, "ioemu:", 6))
+             tmp += 6;
+         virBufferVSprintf(buf, "(dev 'ioemu:%s')", (const char *) tmp);
+     } else
          virBufferVSprintf(buf, "(dev '%s')", (const char *) target);
      if (typ == 0)
          virBufferVSprintf(buf, "(uname 'file:%s')", source);
***************
*** 845,850 ****
--- 924,930 ----
          virBufferVSprintf(buf, "(mode 'r')");
  
      virBufferAdd(buf, ")", 1);
+     virBufferAdd(buf, ")", 1);
      xmlFree(target);
      xmlFree(source);
      return (0);
***************
*** 912,917 ****
--- 992,998 ----
      }
      if (script != NULL)
          virBufferVSprintf(buf, "(script '%s')", script);
+     virBufferAdd(buf, "(type ioemu)", 12);
  
      virBufferAdd(buf, ")", 1);
      if (mac != NULL)
***************
*** 948,953 ****
--- 1029,1035 ----
      xmlXPathContextPtr ctxt = NULL;
      int i, res;
      int bootloader = 0;
+     int hvm = 0;
  
      if (name != NULL)
          *name = NULL;
***************
*** 1072,1077 ****
--- 1154,1160 ----
          if ((tmpobj == NULL) || !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) {
              res = virDomainParseXMLOSDescPV(obj->nodesetval->nodeTab[0], &buf);
          } else {
+             hvm = 1;
              res = virDomainParseXMLOSDescHVM(obj->nodesetval->nodeTab[0], &buf, ctxt);
          }
  
***************
*** 1090,1101 ****
      if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
          (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
  	for (i = 0; i < obj->nodesetval->nodeNr; i++) {
! 	    virBufferAdd(&buf, "(device ", 8);
! 	    res = virDomainParseXMLDiskDesc(obj->nodesetval->nodeTab[i], &buf);
  	    if (res != 0) {
  		goto error;
  	    }
- 	    virBufferAdd(&buf, ")", 1);
  	}
      }
      xmlXPathFreeObject(obj);
--- 1173,1182 ----
      if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
          (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
          for (i = 0; i < obj->nodesetval->nodeNr; i++) {
!             res = virDomainParseXMLDiskDesc(obj->nodesetval->nodeTab[i], &buf, hvm);
              if (res != 0) {
                  goto error;
              }
          }
      }
      xmlXPathFreeObject(obj);


More information about the libvir-list mailing list