Index: libguestfs-1.32.4/fish/options.c
===================================================================
--- libguestfs-1.32.4.orig/fish/options.c
+++ libguestfs-1.32.4/fish/options.c
@@ -280,7 +280,33 @@ display_mountpoints_on_failure (const ch
            guestfs_int_program_name);
 
   for (i = 0; fses[i] != NULL; i += 2) {
-    CLEANUP_FREE char *p = guestfs_canonical_device_name (g, fses[i]);
+    CLEANUP_FREE char *p = NULL;
+    CLEANUP_FREE char *device = guestfs_mountable_device (g, fses[i]);
+    CLEANUP_FREE char *subvolume = NULL;
+
+    guestfs_push_error_handler (g, NULL, NULL);
+
+    subvolume = guestfs_mountable_subvolume (g, fses[i]);
+    if (subvolume == NULL && guestfs_last_errno (g) != EINVAL) {
+      fprintf (stderr,
+               _("%s: cannot determine the subvolume for %s: %s (%d)\n"),
+              guestfs_int_program_name, fses[i],
+              guestfs_last_error (g), guestfs_last_errno (g));
+      exit (EXIT_FAILURE);
+    }
+
+    guestfs_pop_error_handler (g);
+
+    /* Reformat the internal btrfsvol string into a valid mount option */
+    if (device && subvolume) {
+      if (asprintf (&p, "%s:/:subvol=%s", device, subvolume) == -1) {
+        perror ("asprintf");
+        exit (EXIT_FAILURE);
+      }
+    } else {
+      p = guestfs_canonical_device_name (g, fses[i]);
+    }
+
     fprintf (stderr, "%s: \t%s (%s)\n", guestfs_int_program_name,
              p ? p : fses[i], fses[i+1]);
   }
Index: libguestfs-1.32.4/generator/actions.ml
===================================================================
--- libguestfs-1.32.4.orig/generator/actions.ml
+++ libguestfs-1.32.4/generator/actions.ml
@@ -1290,6 +1290,32 @@ Please read L<guestfs(3)/INSPECTION> for
 See also C<guestfs_inspect_get_mountpoints>." };
 
   { defaults with
+    name = "mountable_device"; added = (1, 33, 15);
+    style = RString "device", [Mountable "mountable"], [];
+    shortdesc = "extract the device part of a mountable";
+    longdesc = "\
+Returns the device name of a mountable. In quite a lot of
+cases, the mountable is the device name.
+
+However this doesn't apply for btrfs subvolumes, where the
+mountable is a combination of both the device name and the
+subvolume path (see also C<guestfs_mountable_subvolume> to
+extract the subvolume path of the mountable if any)." };
+
+  { defaults with
+    name = "mountable_subvolume"; added = (1, 33, 15);
+    style = RString "subvolume", [Mountable "mountable"], [];
+    shortdesc = "extract the subvolume part of a mountable";
+    longdesc = "\
+Returns the subvolume path of a mountable. Btrfs subvolumes
+mountables are a combination of both the device name and the
+subvolume path (see also C<guestfs_mountable_device> to extract
+the device of the mountable).
+
+If the mountable does not represent a btrfs subvolume, then
+this function fails and the C<errno> is set to C<EINVAL>." };
+
+  { defaults with
     name = "set_network"; added = (1, 5, 4);
     style = RErr, [Bool "network"], [];
     fish_alias = ["network"]; config_only = true;
@@ -8897,7 +8923,7 @@ I<other> keys." };
 
   { defaults with
     name = "is_lv"; added = (1, 5, 3);
-    style = RBool "lvflag", [Device "device"], [];
+    style = RBool "lvflag", [Mountable "mountable"], [];
     proc_nr = Some 264;
     tests = [
       InitBasicFSonLVM, Always, TestResultTrue (
@@ -8905,9 +8931,9 @@ I<other> keys." };
       InitBasicFSonLVM, Always, TestResultFalse (
         [["is_lv"; "/dev/sda1"]]), []
     ];
-    shortdesc = "test if device is a logical volume";
+    shortdesc = "test if mountable is a logical volume";
     longdesc = "\
-This command tests whether C<device> is a logical volume, and
+This command tests whether C<mountable> is a logical volume, and
 returns true iff this is the case." };
 
   { defaults with
Index: libguestfs-1.32.4/po/POTFILES
===================================================================
--- libguestfs-1.32.4.orig/po/POTFILES
+++ libguestfs-1.32.4/po/POTFILES
@@ -344,6 +344,7 @@ src/libvirt-is-version.c
 src/listfs.c
 src/lpj.c
 src/match.c
+src/mountable.c
 src/osinfo.c
 src/private-data.c
 src/proto.c
Index: libguestfs-1.32.4/src/Makefile.am
===================================================================
--- libguestfs-1.32.4.orig/src/Makefile.am
+++ libguestfs-1.32.4/src/Makefile.am
@@ -121,6 +121,7 @@ libguestfs_la_SOURCES = \
 	listfs.c \
 	lpj.c \
 	match.c \
+	mountable.c \
 	osinfo.c \
 	private-data.c \
 	proto.c \
Index: libguestfs-1.32.4/src/mountable.c
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/src/mountable.c
@@ -0,0 +1,52 @@
+/* libguestfs
+ * Copyright (C) 2016 SUSE LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+#include <string.h>
+#include <errno.h>
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+#include "guestfs-internal-actions.h"
+
+
+char *
+guestfs_impl_mountable_device (guestfs_h *g, const char *mountable)
+{
+  CLEANUP_FREE_INTERNAL_MOUNTABLE struct guestfs_internal_mountable *mnt = NULL;
+
+  mnt = guestfs_internal_parse_mountable (g, mountable);
+  if (mnt == NULL)
+    return NULL;
+
+  return safe_strdup (g, mnt->im_device);
+}
+
+char *
+guestfs_impl_mountable_subvolume (guestfs_h *g, const char *mountable)
+{
+  CLEANUP_FREE_INTERNAL_MOUNTABLE struct guestfs_internal_mountable *mnt = NULL;
+
+  mnt = guestfs_internal_parse_mountable (g, mountable);
+  if (mnt == NULL || STREQ (mnt->im_volume, "")) {
+    guestfs_int_error_errno (g, EINVAL, "not a btrfs subvolume identifier");
+    return NULL;
+  }
+
+  return safe_strdup (g, mnt->im_volume);
+}
Index: libguestfs-1.32.4/v2v/windows_virtio.ml
===================================================================
--- libguestfs-1.32.4.orig/v2v/windows_virtio.ml
+++ libguestfs-1.32.4/v2v/windows_virtio.ml
@@ -26,6 +26,10 @@ open Regedit
 open Types
 open Utils
 
+let scsi_class_guid = "{4D36E97B-E325-11CE-BFC1-08002BE10318}"
+let viostor_pciid = "VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00"
+let vioscsi_pciid = "VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
+
 let virtio_win =
   try Sys.getenv "VIRTIO_WIN"
   with Not_found ->
@@ -47,14 +51,26 @@ let rec install_drivers g inspect system
   else (
     (* Can we install the block driver? *)
     let block : guestcaps_block_type =
-      let source = driverdir // "viostor.sys" in
-      if g#exists source then (
-        let target = sprintf "%s/system32/drivers/viostor.sys" systemroot in
+      let filenames = ["virtio_blk"; "vrtioblk"; "viostor"] in
+      let viostor_driver = try (
+        Some (
+          List.find (
+            fun driver_file ->
+              let source = driverdir // driver_file ^ ".sys" in
+              g#exists source
+          ) filenames
+        )
+      ) with Not_found -> None in
+      match viostor_driver with
+      | Some driver_name -> (
+        let source = driverdir // (driver_name ^ ".sys") in
+        let target = sprintf "%s/system32/drivers/%s.sys" systemroot driver_name in
         let target = g#case_sensitive_path target in
         g#cp source target;
-        add_viostor_to_registry g inspect root current_cs;
-        Virtio_blk
-      ) else (
+        add_guestor_to_registry g root current_cs driver_name
+                                viostor_pciid;
+        Virtio_blk )
+      | None -> (
         warning (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.")
                 inspect.i_major_version inspect.i_minor_version
                 inspect.i_arch virtio_win;
@@ -63,7 +79,12 @@ let rec install_drivers g inspect system
 
     (* Can we install the virtio-net driver? *)
     let net : guestcaps_net_type =
-      if not (g#exists (driverdir // "netkvm.inf")) then (
+      let filenames = ["virtio_net.inf"; "netkvm.inf"] in
+      let has_netkvm =
+        List.exists (
+          fun driver_file -> g#exists (driverdir // driver_file)
+        ) filenames in
+      if not has_netkvm then (
         warning (f_"there is no virtio network driver for this version of Windows (%d.%d %s).  virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.")
                 inspect.i_major_version inspect.i_minor_version
                 inspect.i_arch virtio_win;
@@ -88,270 +109,66 @@ let rec install_drivers g inspect system
     (block, net, video)
   )
 
-and add_viostor_to_registry g inspect root current_cs =
-  let { i_major_version = major; i_minor_version = minor;
-        i_arch = arch } = inspect in
-  if (major == 6 && minor >= 2) || major >= 7 then (* Windows >= 8 *)
-    add_viostor_to_driver_database g root arch current_cs
-  else                          (* Windows <= 7 *)
-    add_viostor_to_critical_device_database g root current_cs
+and add_guestor_to_registry g root current_cs drv_name drv_pciid =
+  let ddb_node = g#hivex_node_get_child root "DriverDatabase" in
 
-and add_viostor_to_critical_device_database g root current_cs =
-  (* See http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/
-   * NB: All these edits are in the HKLM\SYSTEM hive.  No other
-   * hive may be modified here.
-   *)
-  let regedits = [
-      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00000000" ],
-      [ "Service", REG_SZ "viostor";
-        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
-
-      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00020000" ],
-      [ "Service", REG_SZ "viostor";
-        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
-
-      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00021af4" ],
-      [ "Service", REG_SZ "viostor";
-        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
-
-      [ current_cs; "Control"; "CriticalDeviceDatabase"; "pci#ven_1af4&dev_1001&subsys_00021af4&rev_00" ],
-      [ "Service", REG_SZ "viostor";
-        "ClassGUID", REG_SZ "{4D36E97B-E325-11CE-BFC1-08002BE10318}" ];
-
-      [ current_cs; "Services"; "viostor" ],
+  let regedits =
+    if ddb_node = 0L then
+      cdb_regedits current_cs drv_name drv_pciid
+    else
+      ddb_regedits current_cs drv_name drv_pciid in
+
+  let drv_sys_path = sprintf "system32\\drivers\\%s.sys" drv_name in
+  let common_regedits = [
+      [ current_cs; "Services"; drv_name ],
       [ "Type", REG_DWORD 0x1_l;
         "Start", REG_DWORD 0x0_l;
         "Group", REG_SZ "SCSI miniport";
         "ErrorControl", REG_DWORD 0x1_l;
-        "ImagePath", REG_EXPAND_SZ "system32\\drivers\\viostor.sys";
-        "Tag", REG_DWORD 0x21_l ];
-
-      [ current_cs; "Services"; "viostor"; "Parameters" ],
-      [ "BusType", REG_DWORD 0x1_l ];
+        "ImagePath", REG_EXPAND_SZ drv_sys_path ];
+  ] in
 
-      [ current_cs; "Services"; "viostor"; "Parameters"; "MaxTransferSize" ],
-      [ "ParamDesc", REG_SZ "Maximum Transfer Size";
-        "type", REG_SZ "enum";
-        "default", REG_SZ "0" ];
-
-      [ current_cs; "Services"; "viostor"; "Parameters"; "MaxTransferSize"; "enum" ],
-      [ "0", REG_SZ "64  KB";
-        "1", REG_SZ "128 KB";
-        "2", REG_SZ "256 KB" ];
-
-      [ current_cs; "Services"; "viostor"; "Parameters"; "PnpInterface" ],
-      [ "5", REG_DWORD 0x1_l ];
-
-      [ current_cs; "Services"; "viostor"; "Enum" ],
-      [ "0", REG_SZ "PCI\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\\3&13c0b0c5&0&20";
-        "Count", REG_DWORD 0x1_l;
-        "NextInstance", REG_DWORD 0x1_l ];
-    ] in
+  reg_import g root (regedits @ common_regedits)
 
-  reg_import g root regedits
+and cdb_regedits current_cs drv_name drv_pciid =
+  (* See http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/
+   * NB: All these edits are in the HKLM\SYSTEM hive.  No other
+   * hive may be modified here.
+   *)
+  [
+    [ current_cs; "Control"; "CriticalDeviceDatabase";
+      "PCI#" ^ drv_pciid ],
+    [ "Service", REG_SZ drv_name;
+      "ClassGUID", REG_SZ scsi_class_guid ];
+  ]
 
-and add_viostor_to_driver_database g root arch current_cs =
+and ddb_regedits current_cs drv_name drv_pciid =
   (* Windows >= 8 doesn't use the CriticalDeviceDatabase.  Instead
    * one must add keys into the DriverDatabase.
    *)
 
-  let viostor_inf =
-    let arch =
-      match arch with
-      | "x86_64" -> "amd64"
-      | "i386" | "i486" | "i585" | "i686" -> "x86"
-      | _ ->
-         error (f_"when adding viostor to the DriverDatabase, unknown architecture: %s") arch in
-    (* XXX I don't know what the significance of the c863.. string is.  It
-     * may even be random.
-     *)
-    sprintf "viostor.inf_%s_%s" arch "c86329aaeb0a7904" in
-
-  let scsi_adapter_guid = "{4d36e97b-e325-11ce-bfc1-08002be10318}" in
-  (* There should be a key
-   *   HKLM\SYSTEM\DriverDatabase\DeviceIds\<scsi_adapter_guid>
-   * We want to add:
-   *   "oem1.inf"=hex(0):
-   * but if we find "oem1.inf" we'll add "oem2.inf" (etc).
-   *)
-  let oem_inf =
-    let path = [ "DriverDatabase"; "DeviceIds"; scsi_adapter_guid ] in
-    match Windows.get_node g root path with
-    | None ->
-       error (f_"cannot find HKLM\\SYSTEM\\DriverDatabase\\DeviceIds\\%s in the guest registry") scsi_adapter_guid
-    | Some node ->
-       let rec loop node i =
-         let oem_inf = sprintf "oem%d.inf" i in
-         let value = g#hivex_node_get_value node oem_inf in
-         if value = 0_L then oem_inf else loop node (i+1)
-       in
-       let oem_inf = loop node 1 in
-       (* Create the key. *)
-       g#hivex_node_set_value node oem_inf (* REG_NONE *) 0_L "";
-       oem_inf in
-
-  (* There should be a key
-   *   HKLM\SYSTEM\ControlSet001\Control\Class\<scsi_adapter_guid>
-   * There may be subkey(s) of this called "0000", "0001" etc.  We want
-   * to create the next free subkey.  MSFT covers the key here:
-   *   https://technet.microsoft.com/en-us/library/cc957341.aspx
-   * That page incorrectly states that the key has the form "000n".
-   * In fact we observed from real registries that the key is a
-   * decimal number that goes 0009 -> 0010 etc.
-   *)
-  let controller_path =
-    [ current_cs; "Control"; "Class"; scsi_adapter_guid ] in
-  let controller_offset =
-    match Windows.get_node g root controller_path with
-    | None ->
-       error (f_"cannot find HKLM\\SYSTEM\\%s in the guest registry")
-             (String.concat "\\" controller_path)
-    | Some node ->
-       let rec loop node i =
-         let controller_offset = sprintf "%04d" i in
-         let child = g#hivex_node_get_child node controller_offset in
-         if child = 0_L then controller_offset else loop node (i+1)
-       in
-       loop node 0 in
-
-  let regedits = [
-      controller_path @ [ controller_offset ],
-      [ "DriverDate", REG_SZ "6-4-2014";
-        "DriverDateData", REG_BINARY "\x00\x40\x90\xed\x87\x7f\xcf\x01";
-        "DriverDesc", REG_SZ "Red Hat VirtIO SCSI controller";
-        "DriverVersion", REG_SZ "62.71.104.8600" (* XXX *);
-        "InfPath", REG_SZ oem_inf;
-        "InfSection", REG_SZ "rhelscsi_inst";
-        "MatchingDeviceId", REG_SZ "PCI\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00";
-        "ProviderName", REG_SZ "Red Hat, Inc." ];
-
-      [ current_cs; "Enum"; "PCI"; "VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\\3&13c0b0c5&0&38" ],
-      [ "Capabilities", REG_DWORD 0x6_l;
-        "ClassGUID", REG_SZ scsi_adapter_guid;
-        "CompatibleIDs", REG_MULTI_SZ [
-                             "PCI\\VEN_1AF4&DEV_1001&REV_00";
-                             "PCI\\VEN_1AF4&DEV_1001";
-                             "PCI\\VEN_1AF4&CC_010000";
-                             "PCI\\VEN_1AF4&CC_0100";
-                             "PCI\\VEN_1AF4";
-                             "PCI\\CC_010000";
-                             "PCI\\CC_0100";
-                           ];
-        "ConfigFlags", REG_DWORD 0_l;
-        "ContainerID", REG_SZ "{00000000-0000-0000-ffff-ffffffffffff}";
-        "DeviceDesc", REG_SZ (sprintf "@%s,%%rhelscsi.devicedesc%%;Red Hat VirtIO SCSI controller" oem_inf);
-        "Driver", REG_SZ (sprintf "%s\\%s" scsi_adapter_guid controller_offset);
-        "HardwareID", REG_MULTI_SZ [
-                          "PCI\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00";
-                          "PCI\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4";
-                          "PCI\\VEN_1AF4&DEV_1001&CC_010000";
-                          "PCI\\VEN_1AF4&DEV_1001&CC_0100";
-                        ];
-        "LocationInformation", REG_SZ "@System32\\drivers\\pci.sys,#65536;PCI bus %1, device %2, function %3;(0,7,0)";
-        "Mfg", REG_SZ (sprintf "@%s,%%rhel%%;Red Hat, Inc." oem_inf);
-        "ParentIdPrefix", REG_SZ "4&87f7bfb&0";
-        "Service", REG_SZ "viostor";
-        "UINumber", REG_DWORD 0x7_l ];
-
-      [ current_cs; "Services"; "viostor" ],
-      [ "ErrorControl", REG_DWORD 0x1_l;
-        "Group", REG_SZ "SCSI miniport";
-        "ImagePath", REG_EXPAND_SZ "system32\\drivers\\viostor.sys";
-        "Owners", REG_MULTI_SZ [ oem_inf ];
-        "Start", REG_DWORD 0x0_l;
-        "Tag", REG_DWORD 0x58_l;
-        "Type", REG_DWORD 0x1_l ];
-
-      [ current_cs; "Services"; "viostor"; "Parameters" ],
-      [ "BusType", REG_DWORD 0x1_l ];
-
-      [ current_cs; "Services"; "viostor"; "Parameters"; "PnpInterface" ],
-      [ "5", REG_DWORD 0x1_l ];
-
-      [ "DriverDatabase"; "DriverInfFiles"; oem_inf ],
-      [ "", REG_MULTI_SZ [ viostor_inf ];
-        "Active", REG_SZ viostor_inf;
-        "Configurations", REG_MULTI_SZ [ "rhelscsi_inst" ]
-      ];
-
-      [ "DriverDatabase"; "DeviceIds"; "PCI"; "VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00" ],
-      [ oem_inf, REG_BINARY "\x01\xff\x00\x00" ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf ],
-      [ "", REG_SZ oem_inf;
-        "F6", REG_DWORD 0x1_l;
-        "InfName", REG_SZ "viostor.inf";
-        "OemPath", REG_SZ ("X:\\windows\\System32\\DriverStore\\FileRepository\\" ^ viostor_inf);
-        "Provider", REG_SZ "Red Hat, Inc.";
-        "SignerName", REG_SZ "Microsoft Windows Hardware Compatibility Publisher";
-        "SignerScore", REG_DWORD 0x0d000005_l;
-        "StatusFlags", REG_DWORD 0x00000012_l;
-        (* NB: scsi_adapter_guid appears inside this string. *)
-        "Version", REG_BINARY "\x00\xff\x09\x00\x00\x00\x00\x00\x7b\xe9\x36\x4d\x25\xe3\xce\x11\xbf\xc1\x08\x00\x2b\xe1\x03\x18\x00\x40\x90\xed\x87\x7f\xcf\x01\x98\x21\x68\x00\x47\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00" ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst" ],
-      [ "ConfigFlags", REG_DWORD 0_l;
-        "Service", REG_SZ "viostor" ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Device" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Device"; "Interrupt Management" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Device"; "Interrupt Management"; "Affinity Policy" ],
-      [ "DevicePolicy", REG_DWORD 0x00000005_l ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Device"; "Interrupt Management"; "MessageSignaledInterruptProperties" ],
-      [ "MSISupported", REG_DWORD 0x00000001_l;
-        "MessageNumberLimit", REG_DWORD 0x00000002_l ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Services" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Services"; "viostor" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Services"; "viostor"; "Parameters" ],
-      [ "BusType", REG_DWORD 0x00000001_l ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Configurations"; "rhelscsi_inst"; "Services"; "viostor"; "Parameters"; "PnpInterface" ],
-      [ "5", REG_DWORD 0x00000001_l ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Descriptors" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Descriptors"; "PCI" ],
-      [];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Descriptors"; "PCI"; "VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00" ],
-      [ "Configuration", REG_SZ "rhelscsi_inst";
-        "Description", REG_SZ "%rhelscsi.devicedesc%";
-        "Manufacturer", REG_SZ "%rhel%" ];
-
-      [ "DriverDatabase"; "DriverPackages"; viostor_inf; "Strings" ],
-      [ "rhel", REG_SZ "Red Hat, Inc.";
-        "rhelscsi.devicedesc", REG_SZ "Red Hat VirtIO SCSI controller" ];
-    ] in
-
-  reg_import g root regedits;
-
-(*
-       A few more keys which we don't add above.  Note that "oem1.inf" ==
-       6f,00,65,00,6d,00,31,00,2e,00,69,00,6e,00,66,00.
-
-       [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\3&13c0b0c5&0&38\Properties\{540b947e-8b40-45bc-a8a2-6a0b894cbda2}\0007]
-       @=hex(ffff0012):6f,00,65,00,6d,00,31,00,2e,00,69,00,6e,00,66,00,3a,00,50,00,43,00,49,00,5c,00,56,00,45,00,4e,00,5f,00,31,00,41,00,46,00,34,00,26,00,44,00,45,00,56,00,5f,00,31,00,30,00,30,00,31,00,26,00,53,00,55,00,42,00,53,00,59,00,53,00,5f,00,30,00,30,00,30,00,32,00,31,00,41,00,46,00,34,00,26,00,52,00,45,00,56,00,5f,00,30,00,30,00,2c,00,72,00,68,00,65,00,6c,00,73,00,63,00,73,00,69,00,5f,00,69,00,6e,00,73,00,74,00,00,00
-
-       [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\3&13c0b0c5&0&38\Properties\{83da6326-97a6-4088-9453-a1923f573b29}\0003]
-       @=hex(ffff0012):6f,00,65,00,6d,00,31,00,2e,00,69,00,6e,00,66,00,3a,00,32,00,65,00,35,00,31,00,37,00,32,00,63,00,33,00,62,00,33,00,37,00,62,00,65,00,39,00,39,00,38,00,3a,00,72,00,68,00,65,00,6c,00,73,00,63,00,73,00,69,00,5f,00,69,00,6e,00,73,00,74,00,3a,00,36,00,32,00,2e,00,37,00,31,00,2e,00,31,00,30,00,34,00,2e,00,38,00,36,00,30,00,30,00,3a,00,50,00,43,00,49,00,5c,00,56,00,45,00,4e,00,5f,00,31,00,41,00,46,00,34,00,26,00,44,00,45,00,56,00,5f,00,31,00,30,00,30,00,31,00,26,00,53,00,55,00,42,00,53,00,59,00,53,00,5f,00,30,00,30,00,30,00,32,00,31,00,41,00,46,00,34,00,26,00,52,00,45,00,56,00,5f,00,30,00,30,00,00,00
-
-       [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\3&13c0b0c5&0&38\Properties\{a8b865dd-2e3d-4094-ad97-e593a70c75d6}\0005]
-       @=hex(ffff0012):6f,00,65,00,6d,00,31,00,2e,00,69,00,6e,00,66,00,00,00
-*)
+  let drv_inf = "guestor.inf" in
+  let drv_inf_label = drv_inf ^ "_tmp" in
+  let drv_config = "guestor_conf" in
+
+  [
+    [ "DriverDatabase"; "DriverInfFiles"; drv_inf ],
+    [ "", REG_MULTI_SZ [ drv_inf_label ];
+      "Active", REG_SZ drv_inf_label;
+      "Configurations", REG_MULTI_SZ [ drv_config ] ];
+
+    [ "DriverDatabase"; "DeviceIds"; "PCI"; drv_pciid ],
+    [ drv_inf, REG_BINARY "\x01\xff\x00\x00" ];
+
+    [ "DriverDatabase"; "DriverPackages"; drv_inf_label;
+      "Configurations"; drv_config ],
+    [ "ConfigFlags", REG_DWORD 0_l;
+      "Service", REG_SZ drv_name ];
+
+    [ "DriverDatabase"; "DriverPackages"; drv_inf_label;
+      "Descriptors"; "PCI"; drv_pciid ],
+    [ "Configuration", REG_SZ drv_config ];
+  ]
 
 (* Copy the matching drivers to the driverdir; return true if any have
  * been copied.
@@ -359,7 +176,7 @@ and add_viostor_to_driver_database g roo
 and copy_drivers g inspect driverdir =
   let ret = ref false in
   if is_directory virtio_win then (
-    let cmd = sprintf "cd %s && find -type f" (quote virtio_win) in
+    let cmd = sprintf "cd %s && find -L -type f" (quote virtio_win) in
     let paths = external_command cmd in
     List.iter (
       fun path ->
@@ -467,6 +284,8 @@ and virtio_iso_path_matches_guest_os pat
         (6, 3, not_client)
       else if pathelem "w10" || pathelem "win10" then
         (10, 0, is_client)
+      else if pathelem "2k16" || pathelem "win2016" then
+        (10, 0, not_client)
       else
         raise Not_found in
 
Index: libguestfs-1.32.4/appliance/init
===================================================================
--- libguestfs-1.32.4.orig/appliance/init
+++ libguestfs-1.32.4/appliance/init
@@ -47,7 +47,9 @@ ln -s ../run/lock /var/lock
 
 # On Fedora 23, util-linux creates /etc/mtab in %post .. stupid
 # and e2fsprogs fails if the link doesn't exist .. stupid stupid
-ln -s /proc/mounts /etc/mtab
+if ! test -e /etc/mtab; then
+  ln -s /proc/mounts /etc/mtab
+fi
 
 # devtmpfs is required since udev 176
 mount -t devtmpfs /dev /dev
Index: libguestfs-1.32.4/appliance/packagelist.in
===================================================================
--- libguestfs-1.32.4.orig/appliance/packagelist.in
+++ libguestfs-1.32.4/appliance/packagelist.in
@@ -132,18 +132,25 @@ ifelse(SUSE,1,
   dnl It seems no other augeas package depends on it.
   augeas-lenses
   btrfsprogs
+  cdrkit-cdrtools-compat
   cryptsetup
   dhcpcd
+  dhcp-client
   genisoimage
   glibc-locale
   gptfdisk
   hivex
+  initviocons
   iproute2
   iputils
+  ldmtool
   libcap2
+  libhivex0
   libselinux1
   libyajl2
   mkisofs
+  ntfsprogs
+  ntfs-3g
   reiserfs
   systemd
   vim
Index: libguestfs-1.32.4/builder/virt-builder.pod
===================================================================
--- libguestfs-1.32.4.orig/builder/virt-builder.pod
+++ libguestfs-1.32.4/builder/virt-builder.pod
@@ -839,16 +839,17 @@ F<~root/virt-sysprep-firstboot.log>.
 =item Windows
 
 F<rhsrvany.exe>, available from sources at
-L<https://github.com/rwmjones/rhsrvany>, is installed to run the
+L<https://github.com/rwmjones/rhsrvany>, or F<pvvxsvc.exe>, available
+with SUSE VMDP is installed to run the
 first boot scripts.  It is required, and the setup of first boot
 scripts will fail if it is not present.
 
-F<rhsrvany.exe> is copied from the location pointed to by the
+F<rhsrvany.exe> or F<pvvxsvc.exe> is copied from the location pointed to by the
 C<VIRT_TOOLS_DATA_DIR> environment variable; if not set, a compiled-in
 default will be used (something like F</usr/share/virt-tools>).
 
 The output of the first boot scripts is available in the guest as
-F<C:\Program Files\Red Hat\Firstboot\log.txt>.
+F<C:\Program Files\Guestfs\Firstboot\log.txt>.
 
 =back
 
@@ -1819,6 +1820,12 @@ I<--firstboot> or I<--firstboot-command>
 
 See also: C<https://github.com/rwmjones/rhsrvany>
 
+=item F<pvvxsvc.exe>
+
+This is a Windows binary shipped with SUSE VMDP, used to install a "firstboot"
+script in Windows guests.  It is required if you intend to use the
+I<--firstboot> or I<--firstboot-command> options with Windows guests.
+
 =back
 
 =item C<XDG_CACHE_HOME>
Index: libguestfs-1.32.4/customize/firstboot.ml
===================================================================
--- libguestfs-1.32.4.orig/customize/firstboot.ml
+++ libguestfs-1.32.4/customize/firstboot.ml
@@ -185,19 +185,25 @@ module Windows = struct
       try Sys.getenv "VIRT_TOOLS_DATA_DIR"
       with Not_found -> Guestfs_config.datadir // "virt-tools" in
 
-    (* rhsrvany.exe must exist.
+    (* Either rhsrvany.exe or pvvxsvc.exe must exist.
      *
      * (Check also that it's not a dangling symlink but a real file).
      *)
-    let rhsrvany_exe = virt_tools_data_dir // "rhsrvany.exe" in
-    (try
-       let chan = open_in rhsrvany_exe in
-       close_in chan
-     with
-       Sys_error msg ->
-         error (f_"'%s' is missing.  This file is required in order to install Windows firstboot scripts.  You can get it by building rhsrvany (https://github.com/rwmjones/rhsrvany).  Original error: %s")
-           rhsrvany_exe msg
-    );
+    let services = ["rhsrvany.exe"; "pvvxsvc.exe"] in
+    let srvany =
+      try
+        List.find (
+          fun service ->
+            try
+              let chan = open_in (virt_tools_data_dir // service) in
+              close_in chan;
+              true
+            with _ ->
+              false
+        ) services
+      with Not_found ->
+       error (f_"One of rhsrvany.exe or pvvxsvc.exe is missing in %s.  One of them is required in order to install Windows firstboot scripts.  You can get one by building rhsrvany (https://github.com/rwmjones/rhsrvany)")
+         virt_tools_data_dir in
 
     (* Create a directory for firstboot files in the guest. *)
     let firstboot_dir, firstboot_dir_win =
@@ -211,12 +217,12 @@ module Windows = struct
           g#mkdir_p firstboot_dir;
           loop firstboot_dir firstboot_dir_win path
       in
-      loop "" "C:" ["Program Files"; "Red Hat"; "Firstboot"] in
+      loop "" "C:" ["Program Files"; "Guestfs"; "Firstboot"] in
 
     g#mkdir_p (firstboot_dir // "scripts");
 
-    (* Copy rhsrvany to the guest. *)
-    g#upload rhsrvany_exe (firstboot_dir // "rhsrvany.exe");
+    (* Copy pvvxsvc or rhsrvany to the guest. *)
+    g#upload (virt_tools_data_dir // srvany) (firstboot_dir // srvany);
 
     (* Write a firstboot.bat control script which just runs the other
      * scripts in the directory.  Note we need to use CRLF line endings
@@ -232,7 +238,7 @@ set log=%%firstboot%%\\log.txt
 set scripts=%%firstboot%%\\scripts
 set scripts_done=%%firstboot%%\\scripts-done
 
-call :main > \"%%log%%\" 2>&1
+call :main >> \"%%log%%\" 2>&1
 exit /b
 
 :main
@@ -244,17 +250,17 @@ if not exist \"%%scripts_done%%\" (
 
 for %%%%f in (\"%%scripts%%\"\\*.bat) do (
   echo running \"%%%%f\"
-  call \"%%%%f\"
+  move \"%%%%f\" \"%%scripts_done%%\"
+  pushd \"%%scripts_done%%\"
+  call \"%%%%~nf\"
   set elvl=!errorlevel!
   echo .... exit code !elvl!
-  if !elvl! equ 0 (
-    move \"%%%%f\" \"%%scripts_done%%\"
-  )
+  popd
 )
 
 echo uninstalling firstboot service
-rhsrvany.exe -s firstboot uninstall
-" firstboot_dir_win in
+%s -s firstboot uninstall
+" firstboot_dir_win srvany in
 
     g#write (firstboot_dir // "firstboot.bat") (unix2dos firstboot_script);
 
@@ -283,7 +289,7 @@ rhsrvany.exe -s firstboot uninstall
         "Start", REG_DWORD 0x2_l;
         "ErrorControl", REG_DWORD 0x1_l;
         "ImagePath",
-          REG_SZ (firstboot_dir_win ^ "\\rhsrvany.exe -s firstboot");
+          REG_SZ (sprintf "%s\\%s -s firstboot" firstboot_dir_win srvany);
         "DisplayName", REG_SZ "Virt tools firstboot service";
         "ObjectName", REG_SZ "LocalSystem" ];
 
Index: libguestfs-1.32.4/customize/virt-customize.pod
===================================================================
--- libguestfs-1.32.4.orig/customize/virt-customize.pod
+++ libguestfs-1.32.4/customize/virt-customize.pod
@@ -250,6 +250,12 @@ I<--firstboot> or I<--firstboot-command>
 
 See also: C<https://github.com/rwmjones/rhsrvany>
 
+=item F<pvvxsvc.exe>
+
+This is a Windows binary shipped with SUSE VMDP, used to install a "firstboot"
+script in Windows guests.  It is required if you intend to use the
+I<--firstboot> or I<--firstboot-command> options with Windows guests.
+
 =back
 
 =back
Index: libguestfs-1.32.4/sysprep/virt-sysprep.pod
===================================================================
--- libguestfs-1.32.4.orig/sysprep/virt-sysprep.pod
+++ libguestfs-1.32.4/sysprep/virt-sysprep.pod
@@ -550,6 +550,12 @@ I<--firstboot> or I<--firstboot-command>
 
 See also: C<https://github.com/rwmjones/rhsrvany>
 
+=item F<pvvxsvc.exe>
+
+This is a Windows binary shipped with SUSE VMDP, used to install a "firstboot"
+script in Windows guests.  It is required if you intend to use the
+I<--firstboot> or I<--firstboot-command> options with Windows guests.
+
 =back
 
 =back
Index: libguestfs-1.32.4/v2v/convert_linux.ml
===================================================================
--- libguestfs-1.32.4.orig/v2v/convert_linux.ml
+++ libguestfs-1.32.4/v2v/convert_linux.ml
@@ -125,7 +125,7 @@ let rec convert ~keep_serial_console (g
   let installed_kernels : kernel_info list =
     let rex_ko = Str.regexp ".*\\.k?o\\(\\.xz\\)?$" in
     let rex_ko_extract = Str.regexp ".*/\\([^/]+\\)\\.k?o\\(\\.xz\\)?$" in
-    let rex_initrd = Str.regexp "^initr\\(d\\|amfs\\)-.*\\.img$" in
+    let rex_initrd = Str.regexp "^initr\\(d\\|amfs\\)-.*\\(\\.img\\)?$" in
     filter_map (
       function
       | { G.app2_name = name } as app
@@ -158,7 +158,8 @@ let rec convert ~keep_serial_console (g
 
              (* Get/construct the version.  XXX Read this from kernel file. *)
              let version =
-               sprintf "%s-%s" app.G.app2_version app.G.app2_release in
+               let prefix_len = String.length "/lib/modules/" in
+               String.sub modpath prefix_len (String.length modpath - prefix_len) in
 
              (* Find the initramfs which corresponds to the kernel.
               * Since the initramfs is built at runtime, and doesn't have
@@ -173,12 +174,11 @@ let rec convert ~keep_serial_console (g
                let files =
                  List.filter (
                    fun n ->
-                     String.find n app.G.app2_version >= 0 &&
-                       String.find n app.G.app2_release >= 0
+                     String.find n version >= 0
                  ) files in
                (* Don't consider kdump initramfs images (RHBZ#1138184). *)
                let files =
-                 List.filter (fun n -> String.find n "kdump.img" == -1) files in
+                 List.filter (fun n -> String.find n "kdump" == -1) files in
                (* If several files match, take the shortest match.  This
                 * handles the case where we have a mix of same-version non-Xen
                 * and Xen kernels:
@@ -841,10 +841,13 @@ let rec convert ~keep_serial_console (g
       else if family = `SUSE_family
            && g#is_file ~followsymlinks:true "/sbin/mkinitrd" then (
         ignore (
-          g#command [| "/sbin/mkinitrd";
+          g#command [| "/usr/bin/env";
+                       "rootdev=" ^ inspect.i_root;
+                       "/sbin/mkinitrd";
                        "-m"; String.concat " " modules;
                        "-i"; initrd;
-                       "-k"; kernel.ki_vmlinuz |]
+                       "-k"; kernel.ki_vmlinuz;
+                       "-d"; inspect.i_root |]
         )
       )
       else if g#is_file ~followsymlinks:true "/sbin/mkinitrd" then (
Index: libguestfs-1.32.4/v2v/test-v2v-in-place.sh
===================================================================
--- libguestfs-1.32.4.orig/v2v/test-v2v-in-place.sh
+++ libguestfs-1.32.4/v2v/test-v2v-in-place.sh
@@ -97,7 +97,7 @@ mktest ()
 :> "$script"
 :> "$expected"
 
-firstboot_dir="/Program Files/Red Hat/Firstboot"
+firstboot_dir="/Program Files/Guestfs/Firstboot"
 mktest "is-dir \"$firstboot_dir\"" true
 mktest "is-file \"$firstboot_dir/firstboot.bat\"" true
 mktest "is-dir \"$firstboot_dir/scripts\"" true
Index: libguestfs-1.32.4/v2v/test-v2v-virtio-win-iso.sh
===================================================================
--- libguestfs-1.32.4.orig/v2v/test-v2v-virtio-win-iso.sh
+++ libguestfs-1.32.4/v2v/test-v2v-virtio-win-iso.sh
@@ -93,7 +93,7 @@ mktest ()
 :> "$script"
 :> "$expected"
 
-firstboot_dir="/Program Files/Red Hat/Firstboot"
+firstboot_dir="/Program Files/Guestfs/Firstboot"
 mktest "is-dir \"$firstboot_dir\"" true
 mktest "is-file \"$firstboot_dir/firstboot.bat\"" true
 mktest "is-dir \"$firstboot_dir/scripts\"" true
Index: libguestfs-1.32.4/v2v/test-v2v-windows-conversion.sh
===================================================================
--- libguestfs-1.32.4.orig/v2v/test-v2v-windows-conversion.sh
+++ libguestfs-1.32.4/v2v/test-v2v-windows-conversion.sh
@@ -86,7 +86,7 @@ mktest ()
 :> "$script"
 :> "$expected"
 
-firstboot_dir="/Program Files/Red Hat/Firstboot"
+firstboot_dir="/Program Files/Guestfs/Firstboot"
 mktest "is-dir \"$firstboot_dir\"" true
 mktest "is-file \"$firstboot_dir/firstboot.bat\"" true
 mktest "is-dir \"$firstboot_dir/scripts\"" true
Index: libguestfs-1.32.4/v2v/virt-v2v.pod
===================================================================
--- libguestfs-1.32.4.orig/v2v/virt-v2v.pod
+++ libguestfs-1.32.4/v2v/virt-v2v.pod
@@ -167,6 +167,8 @@ OVAs from other hypervisors will not wor
 
 =item RHEL 5 Xen
 
+=item SUSE Xen
+
 =item Citrix Xen
 
 Citrix Xen has not been recently tested.
@@ -336,7 +338,7 @@ Xen remote connections can be used.  Oth
 will not work in general.
 
 See also L</INPUT FROM VMWARE VCENTER SERVER>,
-L</INPUT FROM RHEL 5 XEN> below.
+L</INPUT FROM XEN> below.
 
 =item B<-if> format
 
@@ -1256,9 +1258,10 @@ Perform the conversion of the guest usin
 
 Remove the F<guest.xml> and F<guest-disk*> files.
 
-=head1 INPUT FROM RHEL 5 XEN
+=head1 INPUT FROM XEN
 
-Virt-v2v is able to import Xen guests from RHEL 5 Xen hosts.
+Virt-v2v is able to import Xen guests from RHEL 5 Xen or SLES and
+openSUSE Xen hosts.
 
 Virt-v2v uses libvirt for access to the remote Xen host, and therefore
 the input mode should be I<-i libvirt>.  As this is the default, you
@@ -1852,6 +1855,12 @@ script in the guest during conversion of
 
 See also: C<https://github.com/rwmjones/rhsrvany>
 
+=item F<pvvxsvc.exe>
+
+This is a Windows binary shipped with SUSE VMDP, used to install a "firstboot"
+script in Windows guests.  It is required if you intend to use the
+I<--firstboot> or I<--firstboot-command> options with Windows guests.
+
 =item F<rhev-apt.exe>
 
 (Optional)
Index: libguestfs-1.32.4/v2v/Makefile.am
===================================================================
--- libguestfs-1.32.4.orig/v2v/Makefile.am
+++ libguestfs-1.32.4/v2v/Makefile.am
@@ -291,6 +291,7 @@ TESTS_ENVIRONMENT = $(top_builddir)/run
 TESTS = \
 	test-v2v-i-ova-formats.sh \
 	test-v2v-i-ova-gz.sh \
+	test-v2v-i-ova-subfolders.sh \
 	test-v2v-i-ova-two-disks.sh \
 	test-v2v-copy-to-local.sh
 
Index: libguestfs-1.32.4/v2v/convert_windows.ml
===================================================================
--- libguestfs-1.32.4.orig/v2v/convert_windows.ml
+++ libguestfs-1.32.4/v2v/convert_windows.ml
@@ -43,18 +43,25 @@ let convert ~keep_serial_console (g : G.
     try Sys.getenv "VIRT_TOOLS_DATA_DIR"
     with Not_found -> Guestfs_config.datadir // "virt-tools" in
 
-  (* Check if RHEV-APT exists.  This is optional. *)
-  let rhev_apt_exe = virt_tools_data_dir // "rhev-apt.exe" in
-  let rhev_apt_exe =
+  (* Check if either RHEV-APT or VMDP exists.  This is optional. *)
+  let tools = [`RhevApt, "rhev-apt.exe"; `VmdpExe, "vmdp.exe"] in
+  let installer =
     try
-      let chan = open_in rhev_apt_exe in
-      close_in chan;
-      Some rhev_apt_exe
-    with
-      Sys_error msg ->
-        warning (f_"'%s' is missing.  Unable to install RHEV-APT (RHEV guest agent).  Original error: %s")
-          rhev_apt_exe msg;
-        None in
+      let t, tool = List.find (
+        fun (_, tool) ->
+          try (
+            let exe_path = virt_tools_data_dir // tool in
+            let chan = open_in exe_path in
+            close_in chan;
+            true
+          ) with _ ->
+            false
+      ) tools in
+      Some (t, virt_tools_data_dir // tool)
+    with Not_found -> (
+      warning (f_"Neither rhev-apt.exe nor vmdp.exe can be found.  Unable to install one of them.");
+      None
+    ) in
 
   (* Get the Windows %systemroot%. *)
   let systemroot = g#inspect_get_windows_systemroot inspect.i_root in
@@ -158,19 +165,20 @@ let convert ~keep_serial_console (g : G.
   (* Perform the conversion of the Windows guest. *)
 
   let rec configure_firstboot () =
-    configure_rhev_apt ();
+    (match installer with
+     | None -> ()
+     | Some (`RhevApt, tool_path) -> configure_rhev_apt tool_path
+     | Some (`VmdpExe, tool_path) -> configure_vmdp tool_path
+    );
     unconfigure_xenpv ()
 
-  and configure_rhev_apt () =
+  and configure_rhev_apt tool_path =
     (* Configure RHEV-APT (the RHEV guest agent).  However if it doesn't
      * exist just warn about it and continue.
      *)
-    match rhev_apt_exe with
-    | None -> ()
-    | Some rhev_apt_exe ->
-      g#upload rhev_apt_exe "/rhev-apt.exe"; (* XXX *)
+    g#upload tool_path "/rhev-apt.exe"; (* XXX *)
 
-      let fb_script = "\
+    let fb_script = "\
 @echo off
 
 echo installing rhev-apt
@@ -179,8 +187,38 @@ echo installing rhev-apt
 echo starting rhev-apt
 net start rhev-apt
 " in
-      Firstboot.add_firstboot_script g inspect.i_root
-        "configure rhev-apt" fb_script
+    Firstboot.add_firstboot_script g inspect.i_root
+      "configure rhev-apt" fb_script
+
+  and configure_vmdp tool_path =
+    (* Configure VMDP if possible *)
+    g#upload tool_path "/vmdp.exe";
+
+    let fb_script = "\
+echo V2V first boot script started
+echo Decompressing VMDP installer
+\"\\vmdp.exe\"
+pushd \"VMDP-*\"
+echo Installing VMDP
+setup.exe /eula_accepted /no_reboot
+popd
+" in
+
+    let fb_recover_script = "\
+echo Finishing VMDP installation
+if not exist VMDP-* (
+  \"\\vmdp.exe\"
+)
+pushd \"VMDP-*\"
+setup.exe /eula_accepted /no_reboot
+popd
+" in
+
+    Firstboot.add_firstboot_script g inspect.i_root
+      "configure vmdp" fb_script;
+
+    Firstboot.add_firstboot_script g inspect.i_root
+      "finish vmdp setup" fb_recover_script
 
   and unconfigure_xenpv () =
     match xenpv_uninst with
Index: libguestfs-1.32.4/v2v/input_ova.ml
===================================================================
--- libguestfs-1.32.4.orig/v2v/input_ova.ml
+++ libguestfs-1.32.4/v2v/input_ova.ml
@@ -139,13 +139,14 @@ object
     let rex = Str.regexp "SHA1(\\(.*\\))=\\([0-9a-fA-F]+\\)\r?" in
     List.iter (
       fun mf ->
+        let mf_folder = Filename.dirname mf in
         let chan = open_in mf in
         let rec loop () =
           let line = input_line chan in
           if Str.string_match rex line 0 then (
             let disk = Str.matched_group 1 line in
             let expected = Str.matched_group 2 line in
-            let cmd = sprintf "sha1sum %s" (quote (exploded // disk)) in
+            let cmd = sprintf "sha1sum %s" (quote (mf_folder // disk)) in
             let out = external_command cmd in
             match out with
             | [] ->
@@ -166,6 +167,7 @@ object
     ) mf;
 
     (* Parse the ovf file. *)
+    let ovf_folder = Filename.dirname ovf in
     let xml = read_whole_file ovf in
     let doc = Xml.parse_memory xml in
 
@@ -266,7 +268,7 @@ object
             | Some s -> s in
 
           (* Does the file exist and is it readable? *)
-          let filename = exploded // filename in
+          let filename = ovf_folder // filename in
           Unix.access filename [Unix.R_OK];
 
           (* The spec allows the file to be gzip-compressed, in which case
Index: libguestfs-1.32.4/v2v/test-v2v-i-ova-subfolders.expected
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/v2v/test-v2v-i-ova-subfolders.expected
@@ -0,0 +1,18 @@
+Source guest information (--print-source option):
+
+    source name: 2K8R2EESP1_2_Medium
+hypervisor type: vmware
+         memory: 1073741824 (bytes)
+       nr vCPUs: 1
+   CPU features: 
+       firmware: uefi
+        display: 
+          video: 
+          sound: 
+disks:
+	subfolder/disk1.vmdk (vmdk) [scsi]
+removable media:
+	CD-ROM [ide] in slot 0
+NICs:
+	Network "Network adapter 1"
+
Index: libguestfs-1.32.4/v2v/test-v2v-i-ova-subfolders.ovf
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/v2v/test-v2v-i-ova-subfolders.ovf
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Envelope vmw:buildId="build-1750787" xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vmw="http://www.vmware.com/schema/ovf" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <References>
+    <File ovf:href="disk1.vmdk" ovf:id="file1" ovf:size="7804077568"/>
+  </References>
+  <DiskSection>
+    <Info>Virtual disk information</Info>
+    <Disk ovf:capacity="50" ovf:capacityAllocationUnits="byte * 2^30" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" ovf:populatedSize="18975752192"/>
+  </DiskSection>
+  <NetworkSection>
+    <Info>The list of logical networks</Info>
+    <Network ovf:name="PG-VLAN60">
+      <Description>The PG-VLAN60 network</Description>
+    </Network>
+  </NetworkSection>
+  <VirtualSystem ovf:id="2K8R2EESP1_2_Medium">
+    <Info>A virtual machine</Info>
+    <Name>2K8R2EESP1_2_Medium</Name>
+    <OperatingSystemSection ovf:id="103" vmw:osType="windows7Server64Guest">
+      <Info>The kind of installed guest operating system</Info>
+      <Description>Microsoft Windows Server 2008 R2 (64-bit)</Description>
+    </OperatingSystemSection>
+    <VirtualHardwareSection>
+      <Info>Virtual hardware requirements</Info>
+      <System>
+        <vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
+        <vssd:InstanceID>0</vssd:InstanceID>
+        <vssd:VirtualSystemIdentifier>2K8R2EESP1_2_Medium</vssd:VirtualSystemIdentifier>
+        <vssd:VirtualSystemType>vmx-10</vssd:VirtualSystemType>
+      </System>
+      <Item>
+        <rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
+        <rasd:Description>Number of Virtual CPUs</rasd:Description>
+        <rasd:ElementName>1 virtual CPU(s)</rasd:ElementName>
+        <rasd:InstanceID>1</rasd:InstanceID>
+        <rasd:ResourceType>3</rasd:ResourceType>
+        <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
+      </Item>
+      <Item>
+        <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
+        <rasd:Description>Memory Size</rasd:Description>
+        <rasd:ElementName>1024MB of memory</rasd:ElementName>
+        <rasd:InstanceID>2</rasd:InstanceID>
+        <rasd:ResourceType>4</rasd:ResourceType>
+        <rasd:VirtualQuantity>1024</rasd:VirtualQuantity>
+      </Item>
+      <Item>
+        <rasd:Address>0</rasd:Address>
+        <rasd:Description>SCSI Controller</rasd:Description>
+        <rasd:ElementName>SCSI controller 0</rasd:ElementName>
+        <rasd:InstanceID>3</rasd:InstanceID>
+        <rasd:ResourceSubType>lsilogicsas</rasd:ResourceSubType>
+        <rasd:ResourceType>6</rasd:ResourceType>
+        <vmw:Config ovf:required="false" vmw:key="slotInfo.pciSlotNumber" vmw:value="160"/>
+      </Item>
+      <Item>
+        <rasd:Address>1</rasd:Address>
+        <rasd:Description>IDE Controller</rasd:Description>
+        <rasd:ElementName>IDE 1</rasd:ElementName>
+        <rasd:InstanceID>4</rasd:InstanceID>
+        <rasd:ResourceType>5</rasd:ResourceType>
+      </Item>
+      <Item>
+        <rasd:Address>0</rasd:Address>
+        <rasd:Description>IDE Controller</rasd:Description>
+        <rasd:ElementName>IDE 0</rasd:ElementName>
+        <rasd:InstanceID>5</rasd:InstanceID>
+        <rasd:ResourceType>5</rasd:ResourceType>
+      </Item>
+      <Item ovf:required="false">
+        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
+        <rasd:ElementName>Video card</rasd:ElementName>
+        <rasd:InstanceID>6</rasd:InstanceID>
+        <rasd:ResourceType>24</rasd:ResourceType>
+        <vmw:Config ovf:required="false" vmw:key="enable3DSupport" vmw:value="false"/>
+        <vmw:Config ovf:required="false" vmw:key="use3dRenderer" vmw:value="automatic"/>
+        <vmw:Config ovf:required="false" vmw:key="useAutoDetect" vmw:value="true"/>
+        <vmw:Config ovf:required="false" vmw:key="videoRamSizeInKB" vmw:value="4096"/>
+      </Item>
+      <Item ovf:required="false">
+        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
+        <rasd:ElementName>VMCI device</rasd:ElementName>
+        <rasd:InstanceID>7</rasd:InstanceID>
+        <rasd:ResourceSubType>vmware.vmci</rasd:ResourceSubType>
+        <rasd:ResourceType>1</rasd:ResourceType>
+        <vmw:Config ovf:required="false" vmw:key="allowUnrestrictedCommunication" vmw:value="false"/>
+        <vmw:Config ovf:required="false" vmw:key="slotInfo.pciSlotNumber" vmw:value="32"/>
+      </Item>
+      <Item ovf:required="false">
+        <rasd:AddressOnParent>0</rasd:AddressOnParent>
+        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
+        <rasd:ElementName>CD/DVD drive 1</rasd:ElementName>
+        <rasd:InstanceID>8</rasd:InstanceID>
+        <rasd:Parent>4</rasd:Parent>
+        <rasd:ResourceSubType>vmware.cdrom.atapi</rasd:ResourceSubType>
+        <rasd:ResourceType>15</rasd:ResourceType>
+      </Item>
+      <Item>
+        <rasd:AddressOnParent>0</rasd:AddressOnParent>
+        <rasd:ElementName>Hard disk 1</rasd:ElementName>
+        <rasd:HostResource>ovf:/disk/vmdisk1</rasd:HostResource>
+        <rasd:InstanceID>9</rasd:InstanceID>
+        <rasd:Parent>3</rasd:Parent>
+        <rasd:ResourceType>17</rasd:ResourceType>
+        <vmw:Config ovf:required="false" vmw:key="backing.writeThrough" vmw:value="false"/>
+      </Item>
+      <Item>
+        <rasd:AddressOnParent>7</rasd:AddressOnParent>
+        <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
+        <rasd:Connection>PG-VLAN60</rasd:Connection>
+        <rasd:Description>E1000 ethernet adapter on &quot;PG-VLAN60&quot;</rasd:Description>
+        <rasd:ElementName>Network adapter 1</rasd:ElementName>
+        <rasd:InstanceID>11</rasd:InstanceID>
+        <rasd:ResourceSubType>E1000</rasd:ResourceSubType>
+        <rasd:ResourceType>10</rasd:ResourceType>
+        <vmw:Config ovf:required="false" vmw:key="slotInfo.pciSlotNumber" vmw:value="33"/>
+        <vmw:Config ovf:required="false" vmw:key="wakeOnLanEnabled" vmw:value="true"/>
+      </Item>
+      <vmw:Config ovf:required="false" vmw:key="cpuHotAddEnabled" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="cpuHotRemoveEnabled" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="firmware" vmw:value="efi"/>
+      <vmw:Config ovf:required="false" vmw:key="virtualICH7MPresent" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="virtualSMCPresent" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="memoryHotAddEnabled" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="nestedHVEnabled" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.powerOffType" vmw:value="soft"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.resetType" vmw:value="soft"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.standbyAction" vmw:value="checkpoint"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.suspendType" vmw:value="hard"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.afterPowerOn" vmw:value="true"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.afterResume" vmw:value="true"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.beforeGuestShutdown" vmw:value="true"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.beforeGuestStandby" vmw:value="true"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.syncTimeWithHost" vmw:value="false"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.toolsUpgradePolicy" vmw:value="upgradeAtPowerCycle"/>
+    </VirtualHardwareSection>
+  </VirtualSystem>
+</Envelope>                                 
Index: libguestfs-1.32.4/v2v/test-v2v-i-ova-subfolders.sh
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/v2v/test-v2v-i-ova-subfolders.sh
@@ -0,0 +1,65 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test -i ova option with files located in a subfolder.
+
+unset CDPATH
+export LANG=C
+set -e
+
+if [ -n "$SKIP_TEST_V2V_I_OVA_SUBFOLDERS_SH" ]; then
+    echo "$0: test skipped because environment variable is set"
+    exit 77
+fi
+
+if [ "$(guestfish get-backend)" = "uml" ]; then
+    echo "$0: test skipped because UML backend does not support network"
+    exit 77
+fi
+
+export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+
+. $srcdir/../test-data/guestfs-hashsums.sh
+
+d=test-v2v-i-ova-subfolders.d
+rm -rf $d
+mkdir -p $d/subfolder
+
+cp test-v2v-i-ova-subfolders.ovf $d/subfolder/
+
+pushd $d/subfolder
+
+truncate -s 10k disk1.vmdk
+sha=`do_sha1 disk1.vmdk`
+echo -e "SHA1(disk1.vmdk)=$sha\r" > disk1.mf
+
+cd ..
+tar -cf test.ova subfolder
+popd
+
+# Run virt-v2v but only as far as the --print-source stage, and
+# normalize the output.
+$VG virt-v2v --debug-gc --quiet \
+    -i ova $d/test.ova \
+    --print-source |
+sed 's,[^ \t]*\(subfolder/disk.*\.vmdk\),\1,' > $d/source
+
+# Check the parsed source is what we expect.
+diff -u test-v2v-i-ova-subfolders.expected $d/source
+
+rm -rf $d
Index: libguestfs-1.32.4/cat/filesystems.c
===================================================================
--- libguestfs-1.32.4.orig/cat/filesystems.c
+++ libguestfs-1.32.4/cat/filesystems.c
@@ -477,9 +477,28 @@ do_output_filesystems (void)
       }
     }
     if ((columns & COLUMN_SIZE)) {
-      size = guestfs_blockdev_getsize64 (g, fses[i]);
-      if (size == -1)
+      CLEANUP_FREE char *device = guestfs_mountable_device (g, fses[i]);
+      CLEANUP_FREE char *subvolume = NULL;
+
+      guestfs_push_error_handler (g, NULL, NULL);
+
+      subvolume = guestfs_mountable_subvolume (g, fses[i]);
+      if (subvolume == NULL && guestfs_last_errno (g) != EINVAL) {
+        fprintf (stderr,
+                 _("%s: cannot determine the subvolume for %s: %s: %s\n"),
+                guestfs_int_program_name, fses[i],
+                guestfs_last_error (g),
+                strerror (guestfs_last_errno (g)));
         exit (EXIT_FAILURE);
+      }
+
+      guestfs_pop_error_handler (g);
+
+      if (!device || !subvolume) {
+        size = guestfs_blockdev_getsize64 (g, fses[i]);
+        if (size == -1)
+          exit (EXIT_FAILURE);
+      }
     }
 
     if (is_md (fses[i]))
Index: libguestfs-1.32.4/.gitignore
===================================================================
--- libguestfs-1.32.4.orig/.gitignore
+++ libguestfs-1.32.4/.gitignore
@@ -321,6 +321,7 @@ Makefile.in
 /p2v/stamp-virt-p2v.pod
 /p2v/stamp-virt-p2v-make-disk.pod
 /p2v/stamp-virt-p2v-make-kickstart.pod
+/p2v/stamp-virt-p2v-make-kiwi.pod
 /p2v/test-virt-p2v-pxe.id_rsa
 /p2v/test-virt-p2v-pxe.id_rsa.pub
 /p2v/test-virt-p2v-pxe.img
@@ -335,6 +336,8 @@ Makefile.in
 /p2v/virt-p2v-make-disk.1
 /p2v/virt-p2v-make-kickstart
 /p2v/virt-p2v-make-kickstart.1
+/p2v/virt-p2v-make-kiwi
+/p2v/virt-p2v-make-kiwi.1
 /perl/_build
 /perl/bindtests.pl
 /perl/blib
Index: libguestfs-1.32.4/configure.ac
===================================================================
--- libguestfs-1.32.4.orig/configure.ac
+++ libguestfs-1.32.4/configure.ac
@@ -159,6 +159,8 @@ AC_CONFIG_FILES([p2v/virt-p2v-make-disk]
                 [chmod +x,-w p2v/virt-p2v-make-disk])
 AC_CONFIG_FILES([p2v/virt-p2v-make-kickstart],
                 [chmod +x,-w p2v/virt-p2v-make-kickstart])
+AC_CONFIG_FILES([p2v/virt-p2v-make-kiwi],
+                [chmod +x,-w p2v/virt-p2v-make-kiwi])
 AC_CONFIG_FILES([php/extension/php-for-tests.sh],
                 [chmod +x,-w php/extension/php-for-tests.sh])
 AC_CONFIG_FILES([pick-guests.pl],
Index: libguestfs-1.32.4/p2v/Makefile.am
===================================================================
--- libguestfs-1.32.4.orig/p2v/Makefile.am
+++ libguestfs-1.32.4/p2v/Makefile.am
@@ -21,6 +21,8 @@ EXTRA_DIST = \
 	HACKING \
 	dependencies.m4 \
 	issue \
+	kiwi-config.sh \
+	kiwi-config.xml.in \
 	launch-virt-p2v.in \
 	p2v.ks.in \
 	p2v.service \
@@ -28,15 +30,19 @@ EXTRA_DIST = \
 	virt-p2v-make-disk.in \
 	virt-p2v-make-disk.pod \
 	virt-p2v-make-kickstart.in \
-	virt-p2v-make-kickstart.pod
+	virt-p2v-make-kickstart.pod \
+	virt-p2v-make-kiwi.in \
+	virt-p2v-make-kiwi.pod
 
 CLEANFILES = \
 	stamp-virt-p2v.pod \
 	stamp-virt-p2v-make-disk.pod \
 	stamp-virt-p2v-make-kickstart.pod \
+	stamp-virt-p2v-make-kiwi.pod \
 	virt-p2v.1 \
 	virt-p2v-make-disk.1 \
-	virt-p2v-make-kickstart.1
+	virt-p2v-make-kickstart.1 \
+	virt-p2v-make-kiwi.1
 
 # Although virt-p2v is a regular binary, it is not usually installed
 # in /usr/bin since it only functions when contained in an ISO or PXE
@@ -83,7 +89,7 @@ virt_p2v_LDADD = \
 	../gnulib/lib/libgnu.la
 
 # Scripts to build the disk image, USB key, or kickstart.
-bin_SCRIPTS = virt-p2v-make-disk virt-p2v-make-kickstart
+bin_SCRIPTS = virt-p2v-make-disk virt-p2v-make-kickstart virt-p2v-make-kiwi
 
 dependencies_files = \
 	dependencies.archlinux \
@@ -103,6 +109,8 @@ virtp2vdatadir = $(datadir)/virt-p2v
 virtp2vdata_DATA = \
 	$(dependencies_files) \
 	issue \
+	kiwi-config.sh \
+	kiwi-config.xml.in \
 	launch-virt-p2v \
 	p2v.ks.in \
 	p2v.service
@@ -118,12 +126,14 @@ launch-virt-p2v: launch-virt-p2v.in
 man_MANS = \
 	virt-p2v.1 \
 	virt-p2v-make-disk.1 \
-	virt-p2v-make-kickstart.1
+	virt-p2v-make-kickstart.1 \
+	virt-p2v-make-kiwi.1
 
 noinst_DATA = \
 	$(top_builddir)/website/virt-p2v.1.html \
 	$(top_builddir)/website/virt-p2v-make-disk.1.html \
-	$(top_builddir)/website/virt-p2v-make-kickstart.1.html
+	$(top_builddir)/website/virt-p2v-make-kickstart.1.html \
+	$(top_builddir)/website/virt-p2v-make-kiwi.1.html
 
 virt-p2v.1 $(top_builddir)/website/virt-p2v.1.html: stamp-virt-p2v.pod
 
@@ -156,6 +166,17 @@ stamp-virt-p2v-make-kickstart.pod: virt-
 	  --license GPLv2+ \
 	  --warning safe \
 	  $<
+	touch $@
+
+virt-p2v-make-kiwi.1 $(top_builddir)/website/virt-p2v-make-kiwi.1.html: stamp-virt-p2v-make-kiwi.pod
+
+stamp-virt-p2v-make-kiwi.pod: virt-p2v-make-kiwi.pod
+	$(PODWRAPPER) \
+	  --man virt-p2v-make-kiwi.1 \
+	  --html $(top_builddir)/website/virt-p2v-make-kiwi.1.html \
+	  --license GPLv2+ \
+	  --warning safe \
+	  $<
 	touch $@
 
 # Tests.
Index: libguestfs-1.32.4/p2v/dependencies.m4
===================================================================
--- libguestfs-1.32.4.orig/p2v/dependencies.m4
+++ libguestfs-1.32.4/p2v/dependencies.m4
@@ -90,16 +90,18 @@ ifelse(SUSE,1,
   pcre
   libxml2
   gtk2
-  /usr/bin/ssh
-  /usr/bin/qemu-nbd
+  qemu-tools
+  openssh
   curl
   hwdata
-  /usr/bin/xinit
-  /usr/bin/Xorg
+  xinit
+  xorg-x11-server
   xf86-video-*
-  metacity
   NetworkManager
-  nm-connection-editor
-  network-manager-applet
-  dbus-x11
+  xf86-input-*
+  icewm-lite
+  dbus-1-x11
+  yast2-network
+  libyui-qt
+  SuSEfirewall2
 )
Index: libguestfs-1.32.4/p2v/gui.c
===================================================================
--- libguestfs-1.32.4.orig/p2v/gui.c
+++ libguestfs-1.32.4/p2v/gui.c
@@ -381,7 +381,10 @@ test_connection_thread (void *data)
 static void
 configure_network_button_clicked (GtkWidget *w, gpointer data)
 {
-  ignore_value (system ("nm-connection-editor &"));
+  if (access ("/sbin/yast2", X_OK) >= 0)
+    ignore_value (system ("yast2 lan &"));
+  else
+    ignore_value (system ("nm-connection-editor &"));
 }
 
 static void
Index: libguestfs-1.32.4/p2v/kiwi-config.sh
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/p2v/kiwi-config.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+#================
+# FILE          : config.sh
+#----------------
+# PROJECT       : OpenSuSE KIWI Image System
+# COPYRIGHT     : (c) 2006 SUSE LINUX Products GmbH. All rights reserved
+#               :
+# AUTHOR        : Marcus Schaefer <ms@suse.de>
+#======================================
+# Functions...
+#--------------------------------------
+test -f /.kconfig && . /.kconfig
+test -f /.profile && . /.profile
+
+#======================================
+# Greeting...
+#--------------------------------------
+echo "Configure image: [$kiwi_iname]..."
+
+#======================================
+# Mount system filesystems
+#--------------------------------------
+baseMount
+
+#======================================
+# Setup baseproduct link
+#--------------------------------------
+suseSetupProduct
+
+#======================================
+# Add missing gpg keys to rpm
+#--------------------------------------
+suseImportBuildKey
+
+#======================================
+# Activate services
+#--------------------------------------
+suseInsertService p2v
+
+#======================================
+# Setup default target, multi-user
+#--------------------------------------
+baseSetRunlevel 3
+
+#==========================================
+# remove package docs
+#------------------------------------------
+rm -rf /usr/share/doc/packages/*
+rm -rf /usr/share/doc/manual/*
+rm -rf /opt/kde*
+
+# Update the default getty target to login automatically as root without
+# prompting for a password
+sed -i 's/^ExecStart=\(.*\)/ExecStart=\1 -a root/' \
+    /usr/lib/systemd/system/getty@.service
+
+# Reserve tty1 as a getty so we can document it clearly
+echo ReserveVT=1 >> /etc/systemd/logind.conf
+
+sed -i 's/^ROOT_USES_LANG=.*$/ROOT_USES_LANG="yes"/' \
+    /etc/sysconfig/language
+
+#======================================
+# SuSEconfig
+#--------------------------------------
+suseConfig
+
+#======================================
+# Umount kernel filesystems
+#--------------------------------------
+baseCleanMount
+
+exit 0
Index: libguestfs-1.32.4/p2v/kiwi-config.xml.in
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/p2v/kiwi-config.xml.in
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<image schemaversion="6.2" name="p2v-__KIWI_BOOT__" displayname="p2v___PACKAGE_VERSION_____KIWI_BOOT__">
+  <description type="system">
+    <author>Marcus Schäfer</author>
+    <contact>ms@suse.com</contact>
+    <specification>P2V __PACKAGE_VERSION__</specification>
+  </description>
+  <profiles>
+    <profile name="vmxFlavour" description="VMX with default kernel" import="true"/>
+    <profile name="netboot" description="compressed rootfs image for pxe"/>
+  </profiles>
+  <preferences>
+      <type image="iso" primary="true" boot="isoboot/suse-__KIWI_BOOT__" flags="overlay" hybrid="true" firmware="uefi" kernelcmdline="splash"/>
+    <version>__PACKAGE_VERSION__</version>
+    <packagemanager>zypper</packagemanager>
+    <locale>en_US</locale>
+    <keytable>us.map.gz</keytable>
+    <hwclock>utc</hwclock>
+    <bootloader-theme>__BRANDING__</bootloader-theme>
+    <bootsplash-theme>__BRANDING__</bootsplash-theme>
+    <rpm-excludedocs>true</rpm-excludedocs>
+    <rpm-check-signatures>false</rpm-check-signatures>
+  </preferences>
+  <preferences profiles="netboot">
+    <type image="pxe" filesystem="overlayfs" boot="netboot/suse-__KIWI_BOOT__">
+      <pxedeploy server="192.168.100.2" blocksize="4096">
+        <partitions device="/dev/sda">
+          <partition type="swap" number="1" size="5"/>
+          <partition type="L" number="2" size="image" mountpoint="/" target="true"/>
+          <partition type="L" number="3" target="false"/>
+        </partitions>
+        <union ro="/dev/sda2" rw="/dev/sda3" type="overlayfs"/>
+      </pxedeploy>
+    </type>
+  </preferences>
+  <preferences profiles="vmxFlavour">
+      <type image="vmx" filesystem="ext3" boot="vmxboot/suse-__KIWI_BOOT__" format="vmdk" bootloader="grub2" firmware="uefi" kernelcmdline="splash" bootpartition="false">
+      <systemdisk name="systemVG"/>
+      <machine memory="512" guestOS="suse" HWversion="4">
+        <vmdisk id="0" controller="ide"/>
+        <vmnic driver="e1000" interface="0" mode="bridged"/>
+      </machine>
+    </type>
+  </preferences>
+  <users group="root">
+    <user password="p2v" pwdformat="plain" home="/root" name="root"/>
+  </users>
+  <!--__REPOS__-->
+  <packages type="image" patternType="onlyRequired">
+    <package name="__BASE_PATTERN__"/>
+    <package name="plymouth-branding-__BRANDING__" bootinclude="true"/>
+    <package name="grub2-branding-__BRANDING__" bootinclude="true"/>
+    <package name="iputils"/>
+    <package name="grub2"/>
+    <package name="grub2-x86_64-efi"/>
+    <package name="syslinux"/>
+    <package name="lvm2"/>
+    <package name="plymouth"/>
+    <package name="fontconfig"/>
+    <package name="fonts-config"/>
+    <package name="tar"/>
+    <package name="systemd"/>
+    <package name="systemd-sysvinit"/>
+    <package name="dracut"/>
+    <package name="wicked"/>
+    <package name="iproute2"/>
+    <package name="sudo"/>
+    <package name="dhcp-client"/>
+    <package name="which"/>
+    <!-- virt-p2v dependencies from dependencies.suse -->
+<!--__DEPENDENCIES__-->
+  </packages>
+  <packages type="iso">
+      <package name="gfxboot-branding-__BRANDING__" bootinclude="true" bootdelete="true"/>
+  </packages>
+  <packages type="image" profiles="vmxFlavour">
+    <package name="kernel-default" replaces="kernel-xen"/>
+    <package name="kernel-default" replaces="xen-kmp-default"/>
+    <package name="kernel-default" replaces="xen-libs"/>
+    <package name="kernel-default" replaces="xen-tools"/>
+    <package name="kernel-default" replaces="xen"/>
+    <package name="gfxboot-branding-__BRANDING__" bootinclude="true" bootdelete="true"/>
+  </packages>
+  <packages type="bootstrap">
+    <package name="udev"/>
+    <package name="filesystem"/>
+    <package name="glibc-locale"/>
+    <package name="cracklib-dict-full"/>
+    <package name="ca-certificates"/>
+    <package name="__RELEASE_PKG__"/>
+  </packages>
+</image>
Index: libguestfs-1.32.4/p2v/launch-virt-p2v.in
===================================================================
--- libguestfs-1.32.4.orig/p2v/launch-virt-p2v.in
+++ libguestfs-1.32.4/p2v/launch-virt-p2v.in
@@ -22,8 +22,20 @@
 # and virt-p2v.
 if [ "$1" = "run" ]; then
     cd /
-    metacity &
-    nm-applet &
+    ID=
+    if test -f /etc/os-release; then
+        . /etc/os-release
+    fi
+
+    case "$ID" in
+        sles|opensuse)
+            # not all versions of SLE / openSUSE ship metacity and nm-applet
+            icewm &
+            ;;
+        *)
+            metacity &
+            nm-applet &
+    esac
     exec @libexecdir@/virt-p2v
 else
     xinit "$0" run
Index: libguestfs-1.32.4/p2v/utils.c
===================================================================
--- libguestfs-1.32.4.orig/p2v/utils.c
+++ libguestfs-1.32.4/p2v/utils.c
@@ -143,7 +143,7 @@ get_if_vendor (const char *if_name, int
  */
 
 /* XXX We could make this configurable. */
-#define NETWORK_ONLINE_COMMAND "nm-online -t 30"
+#define NETWORK_ONLINE_COMMAND "nm-online -t 30 -x"
 
 void
 wait_network_online (const struct config *config)
Index: libguestfs-1.32.4/p2v/virt-p2v-make-disk.pod
===================================================================
--- libguestfs-1.32.4.orig/p2v/virt-p2v-make-disk.pod
+++ libguestfs-1.32.4/p2v/virt-p2v-make-disk.pod
@@ -148,6 +148,7 @@ L</FILES> above).  If not set, a compile
 
 L<virt-p2v(1)>,
 L<virt-p2v-make-kickstart(1)>,
+L<virt-p2v-make-kiwi(1)>,
 L<virt-v2v(1)>,
 L<http://libguestfs.org/>.
 
Index: libguestfs-1.32.4/p2v/virt-p2v-make-kiwi.in
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/p2v/virt-p2v-make-kiwi.in
@@ -0,0 +1,228 @@
+#!/bin/bash -
+# @configure_input@
+# virt-p2v-make-kiwi
+# Copyright (C) 2016 SUSE.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+unset CDPATH
+
+program="virt-p2v-make-kiwi"
+version="@PACKAGE_VERSION@"
+
+TEMP=`getopt \
+        -o o:V \
+        --long help,inject-ssh-identity:,output:,version \
+        -n $program -- "$@"`
+if [ $? != 0 ]; then
+    echo "$program: problem parsing the command line arguments"
+    exit 1
+fi
+eval set -- "$TEMP"
+
+usage ()
+{
+    echo "Usage:"
+    echo "  $program [--options] [-o kiwi-folder]"
+    echo
+    echo "Read $program(1) man page for more information."
+    exit $1
+}
+
+output=p2v.kiwi
+ssh_identity=
+
+while true; do
+    case "$1" in
+        --inject-ssh-identity)
+            ssh_identity="$2"
+            shift 2;;
+        -o|--output)
+            output="$2"
+            shift 2;;
+        -V|--version)
+            echo "$program $version"
+            exit 0;;
+        --help)
+            usage 0;;
+        --)
+            shift
+            break;;
+        *)
+            echo "internal error ($1)"
+            exit 1;;
+    esac
+done
+
+set -e
+
+# Deal with stupid autotools libexecdir-not-expandable crap.
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+libexecdir="@libexecdir@"
+
+if [ -n "$VIRT_P2V_DATA_DIR" ]; then
+    datadir="$VIRT_P2V_DATA_DIR"
+    host_libexecdir="$VIRT_P2V_DATA_DIR"
+else
+    datadir="@datadir@/virt-p2v"
+    host_libexecdir="@libexecdir@"
+fi
+
+# Dependencies.  Since kiwi is SUSE-specific, only include
+# dependencies.suse here.
+depsfile="$datadir/dependencies.suse"
+if [ ! -f "$depsfile" ]; then
+    echo "$0: cannot find dependencies file ($depsfile)"
+    exit 1
+fi
+dependencies=
+while read line; do
+    if [ -n "$line" ]; then
+        depname=$(echo $line | awk '{gsub(/ /, "", $0); print}')
+        pkg="    <package name=\"$depname\"/>"
+        if [ -z "$dependencies" ]; then
+            dependencies="$pkg"
+        else
+            dependencies="$dependencies
+$pkg"
+        fi
+    fi
+done < $depsfile
+
+# Compute the distro-dependent pieces for kiwi
+branding=
+release_pkg=
+base_pattern=
+kiwi_boot=
+repos=
+. /etc/os-release
+case "$NAME" in
+    SLES)
+        branding="SLE"
+        release_pkg="sles-release"
+        base_pattern="patterns-sles-Minimal"
+        case "$VERSION_ID" in
+            12)
+                kiwi_boot="SLES12"
+                repos="http://download.suse.de/ibs/SUSE:/SLE-12:/Update/standard
+                      http://download.suse.de/ibs/SUSE:/SLE-12:/GA/standard"
+                ;;
+            12.1)
+                kiwi_boot="SLES12"
+                repos="http://download.suse.de/ibs/SUSE:/SLE-12-SP1:/Update/standard
+                      http://download.suse.de/ibs/SUSE:/SLE-12-SP1:/GA/standard
+                      http://download.suse.de/ibs/SUSE:/SLE-12:/Update/standard
+                      http://download.suse.de/ibs/SUSE:/SLE-12:/GA/standard"
+                ;;
+            *)
+                echo "Unsupported distribution $NAME $VERSION_ID"
+                exit 1;;
+        esac;;
+    openSUSE*)
+        branding="openSUSE"
+        release_pkg="openSUSE-release"
+        base_pattern="patterns-openSUSE-base"
+        case "$VERSION" in
+            13.1\ *)
+                kiwi_boot="13.1"
+                repos="obs://13.1/repo/oss"
+                ;;
+            13.2\ *)
+                kiwi_boot="13.2"
+                repos="obs://13.2/repo/oss"
+                ;;
+            42.1)
+                kiwi_boot="leap42.1"
+                repos="obs://leap/42.1/repo/oss"
+                ;;
+            *\ \(Tumbleweed\))
+                kiwi_boot="leap42.1"
+                repos="obs://openSUSE:Factory/standard"
+                ;;
+            *)
+                echo "Unsupported distribution $NAME $VERSION_ID"
+                exit 1;;
+        esac;;
+    *)
+        echo "Unsupported distribution $NAME $VERSION"
+        exit 1;;
+esac
+
+# Compute the repos
+repos_xml=
+for repo in $repos; do
+    repos_xml="  <repository type=\"rpm-md\">\n    <source path=\"$repo\"/>\n  </repository>\n$repos_xml"
+done
+
+mkdir $output
+cp $datadir/kiwi-config.sh $output/config.sh
+
+mkdir -p $output/root/etc/sysconfig/network
+cat >$output/root/etc/sysconfig/network/ifcfg-eth0 << EOF
+BOOTPROTO='dhcp'
+MTU=''
+REMOTE_IPADDR=''
+STARTMODE='onboot'
+EOF
+
+mkdir -p $output/root/etc/systemd/system
+cp $datadir/p2v.service $output/root/etc/systemd/system
+
+mkdir -p $output/root/etc/udev/rules.d
+cat >$output/root/etc/udev/rules.d/70-persistent-net.rules <<EOF
+SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="?*", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="?*", NAME="eth0"
+EOF
+
+cp $datadir/issue $output/root/etc/issue
+
+mkdir -p $output/root/usr/bin
+cp $datadir/launch-virt-p2v $output/root/usr/bin
+
+mkdir -p $output/root/$libexecdir
+cp $host_libexecdir/virt-p2v $output/root/$libexecdir
+
+if test "z$ssh_identity" != "z"; then
+    mkdir -p $output/root/var/tmp
+    cp $ssh_identity $output/root/var/tmp/id_rsa
+    chmod 0600 $output/root/var/tmp/id_rsa
+fi
+
+# Now generate the final kiwi config, substituting as necessary.
+@AWK@ \
+  -v "dependencies=$dependencies" \
+  -v "md5sum_virt_p2v=$md5sum_virt_p2v" \
+  -v "libexecdir=$libexecdir" \
+  -v "branding=$branding" \
+  -v "release_pkg=$release_pkg" \
+  -v "base_pattern=$base_pattern" \
+  -v "kiwi_boot=$kiwi_boot" \
+  -v "repos=$repos_xml" \
+  '{
+    gsub (/__PACKAGE_NAME__/, "@PACKAGE_NAME@");
+    gsub (/__PACKAGE_VERSION__/, "@PACKAGE_VERSION@");
+    gsub (/__PACKAGE_VERSION_FULL__/, "@PACKAGE_VERSION_FULL@");
+    gsub (/<!--__DEPENDENCIES__-->/, dependencies);
+    gsub (/__LIBEXECDIR__/, libexecdir);
+    gsub (/__BRANDING__/, branding);
+    gsub (/__RELEASE_PKG__/, release_pkg);
+    gsub (/__BASE_PATTERN__/, base_pattern);
+    gsub (/__KIWI_BOOT__/, kiwi_boot);
+    gsub (/<!--__REPOS__-->/, repos);
+    print;
+  }' \
+  $datadir/kiwi-config.xml.in > $output/config.xml
+
+echo "kiwi config folder written to $output"
Index: libguestfs-1.32.4/p2v/virt-p2v-make-kiwi.pod
===================================================================
--- /dev/null
+++ libguestfs-1.32.4/p2v/virt-p2v-make-kiwi.pod
@@ -0,0 +1,184 @@
+=head1 NAME
+
+virt-p2v-make-kiwi - Build the virt-p2v kiwi configuration
+
+=head1 SYNOPSIS
+
+ virt-p2v-make-kiwi [--inject-ssh-identity path] [-o kiwi-folder]
+
+=head1 DESCRIPTION
+
+L<virt-p2v(1)> converts a physical machine to run virtualized on KVM,
+managed by libvirt, OpenStack, oVirt, Red Hat Enterprise
+Virtualisation (RHEV), or one of the other targets supported by
+L<virt-v2v(1)>.
+
+Kiwi is a tool used mainly by SUSE Linux Enterprise and openSUSE to
+build live CDs, make appliances and so on. It is driven by a few files
+including an xml description of the machine.
+
+virt-p2v-make-kiwi builds a folder containing all the pieces needed for
+kiwi to build a bootable P2V live CD ISO, USB key, or PXE image.  This tool
+only builds the kiwi configuration, but this manual page describes some of
+the ways you can use the kickstart file.
+
+=head1 BUILDING THE KIWI CONFIGURATION
+
+Using virt-p2v-make-kiwi is very simple:
+
+ virt-p2v-make-kiwi
+
+will build a kiwi configuration based on the current machine's distribution.
+
+To control the name of the output folder, use the I<-o> parameter.
+
+=head1 BUILDING A LIVE CD / ISO
+
+Once you have the kiwi configuration folder, you can use L<kiwi(1)> to make a
+live CD:
+
+ sudo kiwi --build p2v.kiwi -d build --type iso
+
+Before running this, you may have to tweak the C<config.xml> file
+to change the locale and keyboard mapping to the one you need.
+
+If running on a SUSE Linux Entreprise Server, add the path to your packages repositories
+using the C<--ignore-repos> and C<--add-repo> kiwi parameters.
+
+The generated ISO image will be placed in the C<build> folder.
+
+=head1 BUILDING A BOOTABLE USB KEY
+
+Use the L<dd(1)> program to write the ISO created above to a USB key:
+
+ sudo dd if=path/to/p2v.iso of=/dev/sdX
+
+=head1 BUILDING A PXE BOOT IMAGE
+
+To create a PXE boot image, run kiwi in such a way:
+
+ sudo kiwi --build $PWD/p2v.kiwi -d build --add-profile netboot --type pxe
+
+For more details on how to use the generated image, report to the kiwi documentation
+on PXE images: L<https://doc.opensuse.org/projects/kiwi/doc/#chap.pxe>
+
+=head1 ADDING AN SSH IDENTITY
+
+You can inject an SSH identity (private key) file to the kiwi config and
+hence into the ISO using the I<--inject-ssh-identity> option.  Note
+that you I<cannot> inject a key once the ISO has been built.
+
+First create a key pair.  It must have an empty passphrase:
+
+ ssh-keygen -t rsa -N '' -f id_rsa
+
+This creates a private key (C<id_rsa>) and a public key
+(C<id_rsa.pub>) pair.  The public key should be appended to the
+C<authorized_keys> file on the virt-v2v conversion server (usually to
+C</root/.ssh/authorized_keys>).
+
+The private key should be added to the kiwi config and then
+discarded:
+
+ virt-p2v-make-kiwi [...] --inject-ssh-identity id_rsa
+ rm id_rsa
+
+The ISO can then be built from the kickstart in the usual way (see
+above), and it will contain the embedded SSH identity
+(F</var/tmp/id_rsa>).
+
+When booting virt-p2v, specify the URL of the injected file like this:
+
+ │         User name: [root_____________________________] │
+ │                                                        │
+ │          Password: [    <leave this field blank>     ] │
+ │                                                        │
+ │  SSH Identity URL: [file:///var/tmp/id_rsa___________] │
+
+or if using the kernel command line, add:
+
+ p2v.identity=file:///var/tmp/id_rsa
+
+For more information, see L<virt-p2v(1)/SSH IDENTITIES>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+Display help.
+
+=item B<--inject-ssh-identity> id_rsa
+
+Add an SSH identity (private key) file into the kickstart.
+See L</ADDING AN SSH IDENTITY> above.
+
+=item B<-o> OUTPUT
+
+=item B<--output> OUTPUT
+
+Write kiwi configuration to the C<OUTPUT> folder.  If not specified, the default is
+F<p2v.kiwi> in the current directory.
+
+=item B<-V>
+
+=item B<--version>
+
+Display version number and exit.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=item F<$libexecdir/virt-p2v>
+
+The L<virt-p2v(1)> binary which is copied into the kiwi configuration.
+
+The location of the binary can be changed by setting the
+C<VIRT_P2V_DATA_DIR> environment variable.
+
+=item F<$datadir/virt-p2v/issue>
+
+=item F<$datadir/virt-p2v/launch-virt-p2v.in>
+
+=item F<$datadir/virt-p2v/kiwi>
+
+=item F<$datadir/virt-p2v/p2v.service>
+
+Various data files that are used to make the kiwi appliance.
+
+The location of these files can be changed by setting the
+C<VIRT_P2V_DATA_DIR> environment variable.
+
+=back
+
+=head1 ENVIRONMENT VARIABLES
+
+=over 4
+
+=item C<VIRT_P2V_DATA_DIR>
+
+The directory where virt-p2v-make-kiwi looks for data files and
+the virt-p2v binary (see L</FILES> above).  If not set, a compiled-in
+location is used.
+
+=back
+
+=head1 SEE ALSO
+
+L<virt-p2v(1)>,
+L<virt-p2v-make-disk(1)>,
+L<virt-v2v(1)>,
+L<kiwi(1)>,
+L<http://libguestfs.org/>.
+
+=head1 AUTHORS
+
+Cédric Bosdonnat
+
+=head1 COPYRIGHT
+
+Copyright (C) 2016 SUSE Ltd.
Index: libguestfs-1.32.4/p2v/virt-p2v.pod
===================================================================
--- libguestfs-1.32.4.orig/p2v/virt-p2v.pod
+++ libguestfs-1.32.4/p2v/virt-p2v.pod
@@ -725,6 +725,7 @@ control connection to be displayed in th
 
 L<virt-p2v-make-disk(1)>,
 L<virt-p2v-make-kickstart(1)>,
+L<virt-p2v-make-kiwi(1)>,
 L<virt-v2v(1)>,
 L<qemu-nbd(1)>,
 L<ssh(1)>,
Index: libguestfs-1.32.4/daemon/lvm.c
===================================================================
--- libguestfs-1.32.4.orig/daemon/lvm.c
+++ libguestfs-1.32.4/daemon/lvm.c
@@ -863,9 +863,11 @@ lv_canonical (const char *device, char *
 
 /* Test if a device is a logical volume (RHBZ#619793). */
 int
-do_is_lv (const char *device)
+do_is_lv (const mountable_t *mountable)
 {
-  return lv_canonical (device, NULL);
+  if (mountable->type != MOUNTABLE_DEVICE)
+    return 0;
+  return lv_canonical (mountable->device, NULL);
 }
 
 /* Return canonical name of LV to caller (RHBZ#638899). */
Index: libguestfs-1.32.4/mllib/common_utils.ml
===================================================================
--- libguestfs-1.32.4.orig/mllib/common_utils.ml
+++ libguestfs-1.32.4/mllib/common_utils.ml
@@ -833,3 +833,10 @@ let read_first_line_from_file filename =
 let is_regular_file path = (* NB: follows symlinks. *)
   try (Unix.stat path).Unix.st_kind = Unix.S_REG
   with Unix.Unix_error _ -> false
+
+let is_btrfs_subvolume g fs =
+  try
+    ignore (g#mountable_subvolume fs); true
+  with Guestfs.Error msg as exn ->
+    if g#last_errno () = Guestfs.Errno.errno_EINVAL then false
+    else raise exn
Index: libguestfs-1.32.4/mllib/common_utils.mli
===================================================================
--- libguestfs-1.32.4.orig/mllib/common_utils.mli
+++ libguestfs-1.32.4/mllib/common_utils.mli
@@ -273,3 +273,6 @@ val read_first_line_from_file : string -
 
 val is_regular_file : string -> bool
 (** Checks whether the file is a regular file. *)
+
+val is_btrfs_subvolume : Guestfs.guestfs -> string -> bool
+(** Checks if a filesystem is a btrfs subvolume. *)
Index: libguestfs-1.32.4/sysprep/sysprep_operation_fs_uuids.ml
===================================================================
--- libguestfs-1.32.4.orig/sysprep/sysprep_operation_fs_uuids.ml
+++ libguestfs-1.32.4/sysprep/sysprep_operation_fs_uuids.ml
@@ -30,13 +30,15 @@ let rec fs_uuids_perform g root side_eff
   List.iter (function
   | _, "unknown" -> ()
   | dev, typ ->
-    let new_uuid = Common_utils.uuidgen () in
-    try
-      g#set_uuid dev new_uuid
-    with
-      G.Error msg ->
-        warning (f_"cannot set random UUID on filesystem %s type %s: %s")
-          dev typ msg
+    if not (is_btrfs_subvolume g dev) then (
+      let new_uuid = Common_utils.uuidgen () in
+      try
+        g#set_uuid dev new_uuid
+      with
+        G.Error msg ->
+          warning (f_"cannot set random UUID on filesystem %s type %s: %s")
+            dev typ msg
+    )
   ) fses
 
 let op = {
Index: libguestfs-1.32.4/src/inspect-fs-unix.c
===================================================================
--- libguestfs-1.32.4.orig/src/inspect-fs-unix.c
+++ libguestfs-1.32.4/src/inspect-fs-unix.c
@@ -1371,27 +1371,28 @@ check_fstab (guestfs_h *g, struct inspec
     if (vfstype == NULL) return -1;
 
     if (STREQ (vfstype, "btrfs")) {
-      char **opt;
+      size_t i;
 
       snprintf (augpath, sizeof augpath, "%s/opt", *entry);
       CLEANUP_FREE_STRING_LIST char **opts = guestfs_aug_match (g, augpath);
       if (opts == NULL) return -1;
 
-      for (opt = opts; *opt; opt++) {
-        CLEANUP_FREE char *optname = guestfs_aug_get (g, augpath);
+      for (i = 0; opts[i] != NULL; ++i) {
+        CLEANUP_FREE char *optname = NULL, *optvalue = NULL, *subvol = NULL;
+        char *old_mountable;
+
+        optname = guestfs_aug_get (g, opts[i]);
         if (optname == NULL) return -1;
 
         if (STREQ (optname, "subvol")) {
-          CLEANUP_FREE char *subvol = NULL;
-          char *new;
+          optvalue = safe_asprintf (g, "%s/value", opts[i]);
 
-          snprintf (augpath, sizeof augpath, "%s/value", *opt);
-          subvol = guestfs_aug_get (g, augpath);
+          subvol = guestfs_aug_get (g, optvalue);
           if (subvol == NULL) return -1;
 
-          new = safe_asprintf (g, "btrfsvol:%s/%s", mountable, subvol);
-          free (mountable);
-          mountable = new;
+          old_mountable = mountable;
+          mountable = safe_asprintf (g, "btrfsvol:%s/%s", mountable, subvol);
+          free (old_mountable);
         }
       }
     }
