File win_convert_on_suse.patch of Package virt-v2v

In order to convert Windows guests on a SUSE host, several modifications are
required to support the VMDP.

 lib/Sys/VirtConvert/Converter/Windows.pm |  292 ++++++++++++++++++-------------
 v2v/virt-v2v.db                          |   27 ++
 v2v/virt-v2v.pl                          |   26 ++
 3 files changed, 220 insertions(+), 125 deletions(-)

diff -Nurp a/lib/Sys/VirtConvert/Converter/Windows.pm b/lib/Sys/VirtConvert/Converter/Windows.pm
--- a/lib/Sys/VirtConvert/Converter/Windows.pm	2014-01-17 16:13:05.587686655 -0700
+++ b/lib/Sys/VirtConvert/Converter/Windows.pm	2014-01-17 10:45:25.951024357 -0700
@@ -1,5 +1,6 @@
 # Sys::VirtConvert::Converter::Windows
 # Copyright (C) 2009-2012 Red Hat Inc.
+# Copyright (C) 2013 SUSE Inc.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -53,7 +54,7 @@ Sys::VirtConvert::Converter::Windows - P
 Sys::VirtConvert::Converter::Windows does the "pre-conversion" steps
 required to get a Windows guest to boot on KVM.  Unlike the associated
 L<Sys::VirtConvert::Converter::Linux(3)> module, this doesn't do a full
-conversion of Windows.  Instead it just installs the viostor (Windows
+conversion of Windows.  Instead it just installs the virtio_blk (Windows
 virtio block) driver, so that the Windows guest will be able to boot
 on the target.  A "RunOnce" script is also added to the VM which does
 all the rest of the conversion the first time the Windows VM is booted
@@ -112,7 +113,7 @@ sub convert
 {
     my $class = shift;
 
-    my ($g, $root, $config, undef, undef) = @_;
+    my ($g, $root, $config, undef, $options) = @_;
 
     my $tmpdir = tempdir (CLEANUP => 1);
 
@@ -137,21 +138,44 @@ sub convert
     my $current_cs = $h_sys->node_get_value($select, 'Current');
     $current_cs = sprintf("ControlSet%03i", $h_sys->value_dword($current_cs));
 
-    # Initialise firstboot
-    # N.B. This may fail, and $firstboot will be undef
-    my ($firstboot, $firstboot_tmp, $firstboot_dir) =
-        _configure_firstboot($g, $root, $config, $tmpdir, $h_sys, $current_cs);
+    # Attempt to install virtio drivers if --vmdp=always was specified, or
+    # if VMDP was found on the source and --vmdp=never was not used
+    my $block;
+    my $net;
+    if (($options->{VMDP} eq "always") || ((_vmdp_installed($g, $h_soft))
+                                       && ($options->{VMDP} ne "never"))) {
+
+        # Initialise firstboot
+        # N.B. This may fail, and $firstboot will be undef
+        my ($firstboot, $firstboot_tmp, $firstboot_dir) =
+            _configure_firstboot($g, $root, $config, $tmpdir, $h_sys,
+                                 $current_cs);
+        _configure_vmdp($g, $root, $config, $firstboot, $firstboot_dir);
+        _unconfigure_xenpv($g, $h_soft, $firstboot);
+
+        _close_firstboot($g, $root, $config, $firstboot, $firstboot_tmp,
+                         $firstboot_dir);
+
+        _disable_services($h_sys, $current_cs);
+
+        ($block, $net) =
+            _prepare_virtio_drivers($g, $root, $windir, $config,
+                                    $h_sys, $h_soft, $current_cs);
 
-    _configure_rhev_apt($g, $root, $config, $firstboot, $firstboot_dir);
-    _unconfigure_xenpv($g, $h_soft, $firstboot);
-
-    _close_firstboot($g, $firstboot, $firstboot_tmp, $firstboot_dir);
-
-    _disable_services($h_sys, $current_cs);
-
-    my ($block, $net) =
-        _prepare_virtio_drivers($g, $root, $windir, $config,
-                                $h_sys, $h_soft, $current_cs);
+    } else {
+        $block = 'ide';
+        $net   = 'rtl8139';
+        logmsg WARN, __x('The Virtual Machine Driver Pack (VMDP) was not '.
+                         'installed.  The guest will be configured with a '.
+                         '{block} block storage adapter and a {net} '.
+                         'network adapter, but no drivers will be installed '.
+                         'for them. If the {block} driver is not already '.
+                         'installed in the guest, it will fail to boot. '.
+                         'If the {net} driver is not already installed in '.
+                         'the guest, you must install it manually after '.
+                         'conversion.',
+                         block => $block, net => $net);
+    }
 
     # Commit and upload the modified registry hives
     $h_sys->commit(undef); undef $h_sys;
@@ -202,52 +226,52 @@ sub _download_hive
 }
 
 # See http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/
-sub _add_viostor_to_registry
+sub _add_virtio_blk_to_registry
 {
     my ($g, $root, $h, $current_cs) = @_;
 
     # Make the changes.
     my $regedits = <<REGEDITS;
 ; Edits to be made to a Windows guest to have
-; it boot from viostor.
+; it boot from virtio_blk.
 
 [HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Control\\CriticalDeviceDatabase\\pci#ven_1af4&dev_1001&subsys_00000000]
-"Service"="viostor"
+"Service"="virtio_blk"
 "ClassGUID"="{4D36E97B-E325-11CE-BFC1-08002BE10318}"
 
 [HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Control\\CriticalDeviceDatabase\\pci#ven_1af4&dev_1001&subsys_00020000]
-"Service"="viostor"
+"Service"="virtio_blk"
 "ClassGUID"="{4D36E97B-E325-11CE-BFC1-08002BE10318}"
 
 [HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Control\\CriticalDeviceDatabase\\pci#ven_1af4&dev_1001&subsys_00021af4]
-"Service"="viostor"
+"Service"="virtio_blk"
 "ClassGUID"="{4D36E97B-E325-11CE-BFC1-08002BE10318}"
 
-[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\viostor]
+[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\virtio_blk]
 "Type"=dword:00000001
 "Start"=dword:00000000
 "Group"="SCSI miniport"
 "ErrorControl"=dword:00000001
-"ImagePath"="system32\\\\drivers\\\\viostor.sys"
+"ImagePath"="system32\\\\drivers\\\\virtio_blk.sys"
 "Tag"=dword:00000021
 
-[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\viostor\\Parameters]
+[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\virtio_blk\\Parameters]
 "BusType"=dword:00000001
 
-[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\viostor\\Parameters\\MaxTransferSize]
+[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\virtio_blk\\Parameters\\MaxTransferSize]
 "ParamDesc"="Maximum Transfer Size"
 "type"="enum"
 "default"="0"
 
-[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\viostor\\Parameters\\MaxTransferSize\\enum]
+[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\virtio_blk\\Parameters\\MaxTransferSize\\enum]
 "0"="64  KB"
 "1"="128 KB"
 "2"="256 KB"
 
-[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\viostor\\Parameters\\PnpInterface]
+[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\virtio_blk\\Parameters\\PnpInterface]
 "5"=dword:00000001
 
-[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\viostor\\Enum]
+[HKEY_LOCAL_MACHINE\\SYSTEM\\$current_cs\\Services\\virtio_blk\\Enum]
 "0"="PCI\\\\VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00\\\\3&13c0b0c5&0&20"
 "Count"=dword:00000001
 "NextInstance"=dword:00000001
@@ -283,8 +307,8 @@ sub _prepare_virtio_drivers
     my ($g, $root, $windir, $config, $h_sys, $h_soft, $current_cs) = @_;
 
     # Copy the target VirtIO drivers to the guest
-    my $driverdir = File::Spec->catdir($g->case_sensitive_path($windir),
-                                       'Drivers', 'VirtIO');
+    my $driverdir = File::Spec->catdir($g->case_sensitive_path('/Program Files'),
+                                       'vmdp', 'virtio');
 
     $g->mkdir_p($driverdir);
 
@@ -312,16 +336,27 @@ sub _prepare_virtio_drivers
         return ($block, $net);
     }
 
-    # We can't proceed if there are any files missing
+    # We can't install any drivers if the defined virtio path is missing
     my $virtio_guest = $config->get_transfer_path($virtio_host);
-    v2vdie __x('Installation failed because the following '.
-               'files referenced in the configuration file are '.
-               'required, but missing: {list}',
-               list => $virtio_host)
-        unless (defined($virtio_host) && $g->exists($virtio_guest));
+    if (!(defined($virtio_host) && $g->exists($virtio_guest))) {
+        my $block = 'ide';
+        my $net   = 'rtl8139';
+
+        logmsg WARN, __x('The installation of virtio drivers failed because '.
+               'the driver path referenced in the configuration file '.
+               '({path}) is required, but missing. The guest will be '.
+               'configured with a {block} block storage adapter and a {net} '.
+               'network adapter, but no drivers will be installed for them. '.
+               'If the {block} driver is not already installed in the guest,'.
+               ' it will fail to boot. If the {net} driver is not already '.
+               'installed in the guest, you must install it manually after '.
+               'conversion.', path => $virtio_host, block => $block,
+               net => $net);
+        return ($block, $net);
+    }
 
     my ($block, $net);
-    my $viostor_guest = File::Spec->catfile($virtio_guest, 'viostor.sys');
+    my $viostor_guest = File::Spec->catfile($virtio_guest, 'virtio_blk.sys');
     if ($g->exists($viostor_guest)) {
         $block = 'virtio';
 
@@ -329,7 +364,7 @@ sub _prepare_virtio_drivers
         $g->cp($viostor_guest,
                $g->case_sensitive_path("$windir/system32/drivers"));
 
-        _add_viostor_to_registry($g, $root, $h_sys, $current_cs);
+        _add_virtio_blk_to_registry($g, $root, $h_sys, $current_cs);
     } else {
         $block = 'ide';
         logmsg WARN, __x('There is no virtio block driver '.
@@ -338,11 +373,11 @@ sub _prepare_virtio_drivers
                          'configured with a {block} block storage '.
                          'adapter, but no driver will be installed for '.
                          'it. If the {block} driver is not already '.
-                         'installed in the guest, it will fail to boot.'.
+                         'installed in the guest, it will fail to boot.',
                          block => $block);
     }
 
-    if ($g->exists(File::Spec->catfile($virtio_guest, 'netkvm.inf'))) {
+    if ($g->exists(File::Spec->catfile($virtio_guest, 'virtio_net.inf'))) {
         $net = 'virtio';
     } else {
         $net = 'rtl8139';
@@ -360,15 +395,28 @@ sub _prepare_virtio_drivers
         $g->cp(File::Spec->catfile($virtio_guest, $file), $driverdir);
     }
 
-    # Find the node \Microsoft\Windows\CurrentVersion
+    # Add virtio installed key (to prevent removal when uninstalling Xen)
+    my $virtiopvd_installed = 0;
     my $node = $h_soft->root();
+    $node = $h_soft->node_get_child($node, 'vmdp');
+    if (defined($node)) {
+        my $key = 'Virtio pvd Installed';
+        my $type = 4;
+        my $data = pack("L", 1);
+        my @new;
+        push (@new, { key => $key, t => $type, value => $data });
+        $h_soft->node_set_value($node, @new);
+    }
+
+    # Find the node \Microsoft\Windows\CurrentVersion
+    $node = $h_soft->root();
     foreach ('Microsoft', 'Windows', 'CurrentVersion') {
         $node = $h_soft->node_get_child($node, $_);
     }
 
     # Update DevicePath, but leave everything else as is
     my @new;
-    my $append = ';%SystemRoot%\Drivers\VirtIO';
+    my $append = ';%ProgramFiles%\vmdp\virtio';
     foreach my $v ($h_soft->node_values($node)) {
         my $key = $h_soft->value_key($v);
         my ($type, $data) = $h_soft->value_value($v);
@@ -400,20 +448,22 @@ sub _configure_firstboot
 {
     my ($g, $root, $config, $tmpdir, $h_sys, $current_cs) = @_;
 
-    # Ensure we have rhsrvany
-    my ($rhsrvany_host) = $config->match_app($g, $root, 'rhsrvany',
+    # Ensure we have pvvxsvc, which is similar in functionality to
+    # RHSrvAny and the Windows SrvAny utility
+    my ($srvany_host) = $config->match_app($g, $root, 'pvvxsvc',
                                              $g->inspect_get_arch($root));
-    if (!defined($rhsrvany_host)) {
+    if (!defined($srvany_host)) {
         logmsg WARN, __x('Unable to configure firstboot service because '.
-                         'rhsrvany is not defined in the configuration file');
+                         'pvvxsvc is not defined in the configuration file');
         return undef;
     }
+    (my $srvany_exe = $srvany_host) =~ s/\S+\///;
 
-    my $rhsrvany_guest = $config->get_transfer_path($rhsrvany_host);
-    unless (defined($rhsrvany_guest) && $g->exists($rhsrvany_guest)) {
+    my $srvany_guest = $config->get_transfer_path($srvany_host);
+    unless (defined($srvany_guest) && $g->exists($srvany_guest)) {
         logmsg WARN, __x('Unable to configure firstboot service because '.
                          '{path} is required, but missing',
-                         path => $rhsrvany_host);
+                         path => $srvany_host);
         return undef;
     }
 
@@ -433,6 +483,7 @@ sub _configure_firstboot
 
 rem firstboot.bat
 rem Copyright (C) 2013 Red Hat Inc.
+rem Copyright (C) 2013 SUSE Inc.
 rem
 rem This program is free software; you can redistribute it and/or
 rem modify it under the terms of the GNU Lesser General Public
@@ -447,14 +498,12 @@ rem
 rem You should have received a copy of the GNU Lesser General Public
 rem License along with this library; if not, write to the Free Software
 rem Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-echo V2V first boot script started > log.txt
 FIRSTBOOT
 
     # Create a directory for firstboot files in the guest
     my $firstboot_dir = ''; # global
     my $firstboot_dir_win = 'C:';
-    foreach my $d ('Program Files', 'RedHat', 'V2V Firstboot') {
+    foreach my $d ('Program Files', 'SUSE', 'V2V Firstboot') {
         $firstboot_dir .= '/'.$d;
         $firstboot_dir_win .= '\\\\'.$d;
 
@@ -462,11 +511,11 @@ FIRSTBOOT
         $g->mkdir_p($firstboot_dir);
     }
 
-    # Copy rhsrvany to guest
-    $g->cp($rhsrvany_guest, $firstboot_dir);
+    # Copy srvany_guest to guest
+    $g->cp($srvany_guest, $firstboot_dir);
 
-    # Add a new rhsrvany service to the system registry to execute firstboot
-    my $rhsrvany_win = $firstboot_dir_win.'\\\\rhsrvany.exe';
+    # Add a new srvany service to the system registry to execute firstboot
+    my $srvany_win = $firstboot_dir_win.'\\\\'.$srvany_exe;
     my $firstboot_win = $firstboot_dir_win.'\\\\firstboot.bat';
 
     my $regedits = <<REGEDITS;
@@ -474,7 +523,7 @@ FIRSTBOOT
 "Type"=dword:00000010
 "Start"=dword:00000002
 "ErrorControl"=dword:00000001
-"ImagePath"="$rhsrvany_win -s v2v-firstboot"
+"ImagePath"="$srvany_win -s v2v-firstboot"
 "DisplayName"="V2V first boot actions"
 "ObjectName"="LocalSystem"
 
@@ -489,26 +538,37 @@ REGEDITS
         if ($_[0] =~ /^HKEY_LOCAL_MACHINE\\SYSTEM(.*)/i) {
             return ($h_sys, $1);
         } else {
-            die "can only make updates to the SYSTEM hive (key was: $_[0])\n"
+            die "can only make updates to the SYSTEM hives (key was: $_[0])\n"
         }
     };
 
     reg_import ($io, \&_map);
 
+    # To be safe, specifically cd to the script directory
+    print $firstboot <<FIRSTBOOT;
+cd "$firstboot_dir_win"
+FIRSTBOOT
+
     return ($firstboot, $firstboot_tmp, $firstboot_dir);
 }
 
 sub _close_firstboot
 {
-    my ($g, $firstboot, $firstboot_tmp, $firstboot_dir) = @_;
+    my ($g, $root, $config, $firstboot, $firstboot_tmp, $firstboot_dir) = @_;
 
     return unless defined($firstboot);
 
-    print $firstboot <<'FIRSTBOOT';
+    my ($srvany_exe) = $config->match_app($g, $root, 'pvvxsvc',
+                                             $g->inspect_get_arch($root));
+    $srvany_exe =~ s/\S+\///;
+
+    if (defined($srvany_exe)) {
+        print $firstboot <<FIRSTBOOT;
 
-echo uninstalling v2v-firstboot service >>log.txt
-rhsrvany.exe -s v2v-firstboot uninstall >>log.txt
+echo uninstalling v2v-firstboot service >> log.txt
+$srvany_exe -s v2v-firstboot uninstall >> log.txt
 FIRSTBOOT
+    }
 
     # Write the completed firstboot script into the guest
     if (defined($firstboot)) {
@@ -517,90 +577,90 @@ FIRSTBOOT
     }
 }
 
-sub _configure_rhev_apt
+sub _configure_vmdp
 {
     my ($g, $root, $config, $firstboot, $firstboot_dir) = @_;
 
-    # Ensure we have rhev-apt
-    my ($rhevapt_host) = $config->match_app($g, $root, 'rhev-apt',
-                                            $g->inspect_get_arch($root));
-    if (!defined($rhevapt_host)) {
-        logmsg WARN, __x('Unable to configure rhev-apt service because '.
-                         'rhev-apt is not defined in the configuration file');
+    # Ensure we have vmdp
+    my ($vmdp_host) = $config->match_app($g, $root, 'vmdp',
+                                             $g->inspect_get_arch($root));
+    if (!defined($vmdp_host)) {
+        logmsg WARN, __x('Unable to configure firstboot service because '.
+                         'vmdp is not defined in the configuration file');
         return;
     }
 
-    my $rhevapt_guest = $config->get_transfer_path($rhevapt_host);
-    unless (defined($rhevapt_guest) && $g->exists($rhevapt_guest)) {
-        logmsg WARN, __x('Unable to configure rhev-apt service because '.
+    my $vmdp_guest = $config->get_transfer_path($vmdp_host);
+    unless (defined($vmdp_guest) && $g->exists($vmdp_guest)) {
+        logmsg WARN, __x('Unable to configure firstboot service because '.
                          '{path} is required, but missing',
-                         path => $rhevapt_host);
-        return;
+                         path => $vmdp_host);
+        return undef;
     }
+    (my $vmdp_exe = $vmdp_host) =~ s/\S+\///;
 
-    # We can't install rhev-apt without firstboot
+    # We can't install the vmdp without firstboot
     # N.B. It may seem more efficient to check this first, but by checking it
     # here the user gets error messages for all missing files in a single
     # conversion
     if (!defined($firstboot)) {
-        logmsg WARN, __x('Unable to configure rhev-apt service without '.
-                         'firstboot');
+        logmsg WARN, __x('Unable to configure vmdp without firstboot');
         return;
     }
 
-    $g->cp($rhevapt_guest, $firstboot_dir);
+    # Copy vmdp to guest
+    $g->cp($vmdp_guest, $firstboot_dir);
 
-    print $firstboot <<'RHEVAPT';
-
-echo installing rhev-apt >>log.txt
-"rhev-apt.exe" /S /v /qn >>log.txt
-
-echo starting rhev-apt >>log.txt
-net start rhev-apt >>log.txt
-RHEVAPT
+    print $firstboot <<FIRSTBOOT;
+echo V2V first boot script started > log.txt
+echo Starting VMDP installation >> log.txt
+$vmdp_exe
+cd "VMDP-WIN*"
+setup.exe /eula_accepted >> ..\\log.txt
+cd ..
+FIRSTBOOT
 }
 
 sub _unconfigure_xenpv
 {
     my ($g, $h_soft, $firstboot) = @_;
 
-    my @regkey = ('Microsoft', 'Windows', 'CurrentVersion', 'Uninstall',
-                  'Red Hat Paravirtualized Xen Drivers for Windows(R)');
+    if (!defined($firstboot)) {
+        logmsg WARN, __x('Unable to uninstall Xen PV drivers without '.
+                         'firstboot');
+        return;
+    }
 
-    # Find the node \Microsoft\Windows\CurrentVersion\Uninstall
-    #               \Red Hat Paravirtualized Xen Drivers for Windows(R)
-    my $node = $h_soft->root();
-    foreach (@regkey) {
-        $node = $h_soft->node_get_child($node, $_);
-        return unless defined($node);
+    # Check for Xenpvd, before configuring the uninstall
+    if (_vmdp_installed($g, $h_soft)) {
+        # The uninstall program for the VMDP is hard coded to
+        # C:\Program Files\vmdp\uninstall.exe.
+        my $uninst = 'C:\Program Files\vmdp\uninstall.exe';
+
+        print $firstboot <<FIRSTBOOT;
+
+echo Uninstalling Xen PV driver >> log.txt
+"$uninst" /xen >> log.txt
+FIRSTBOOT
     }
+}
+
+sub _vmdp_installed
+{
+    my ($g, $h_soft) = @_;
+    my $xenpv_installed = 0;
+
+    my $node = $h_soft->root();
+    $node = $h_soft->node_get_child($node, 'vmdp');
+    return unless defined($node);
 
-    my $uninst;
     foreach my $v ($h_soft->node_values($node)) {
         my $key = $h_soft->value_key($v);
-
-        if ($key eq 'UninstallString') {
-            $uninst = $h_soft->value_value($v);
-            $uninst = decode('UTF-16LE', $uninst);
-            last;
+        if ($key eq 'Xenpvd Installed') {
+            $xenpv_installed = 1;
         }
     }
-
-    logmsg WARN, __x("Can't uninstall Xen PV: {regkey} doesn't contain {value}",
-                     regkey => '\HKLM\SOFTWARE\\'.join(@regkey, '\\'),
-                     value => 'UninstallString');
-
-    # The uninstall program will be uninst.exe. This is a wrapper around
-    # _uninst.exe which prompts the user. As we don't want the user to be
-    # prompted, we run _uninst.ex explicitly.
-    my ($vol, $dir, $file) = File::Spec::Win32->splitpath($uninst);
-    $uninst = File::Spec::Win32->catfile($vol, $dir, '_uninst.exe');
-
-    print $firstboot <<XENPV;
-
-echo Uninstalling Xen PV driver >>log.txt
-"$uninst" >>log.txt
-XENPV
+    return $xenpv_installed;
 }
 
 sub _disable_services
diff -Nurp a/v2v/virt-v2v.db b/v2v/virt-v2v.db
--- a/v2v/virt-v2v.db	2014-01-17 16:13:13.989686073 -0700
+++ b/v2v/virt-v2v.db	2014-01-17 10:40:42.193216710 -0700
@@ -266,9 +266,18 @@ the modifications or additions to /etc/v
 
   <!-- Windows -->
 
-  <!-- Each of these should point to the directory containing the appropriate
-       VirtIO drivers. On some platforms (RHEL 6), the directories below will
-       correspond to directories installed by the 'virtio-win' package. -->
+  <!-- In order for Windows guest conversions to include the virtio drivers,
+       the following components are required:
+
+       - Virtio drivers for each supported Windows platform
+       - The 'pvvxsvc.exe' service utility
+       - The Virtual Machine Driver Pack (VMDP) installation program
+
+       All of these components are available in the 'virt-v2v-vmdp' package,
+       which is part of the Virtual Machine Driver Pack. Information on the
+       VMDP can be found at https://www.suse.com/products/vmdriverpac -->
+
+  <!-- Virtio drivers directories, created by the 'virt-v2v-vmdp' package. -->
   <app os='windows' major='5' minor='1' arch='i386' name='virtio'>
     <path>/usr/share/virtio-win/drivers/i386/WinXP</path>
   </app>
@@ -285,12 +294,14 @@ the modifications or additions to /etc/v
     <path>/usr/share/virtio-win/drivers/amd64/Win2008</path>
   </app>
 
-  <!-- RHSrvAny is compiled as a 32 bit app even on 64 bit Windows -->
-  <app os='windows' name='rhsrvany'>
-    <path>windows/rhsrvany.exe</path>
+  <!-- pvvxsvc is a 32 bit app even on 64 bit Windows -->
+  <app os='windows' name='pvvxsvc'>
+    <path>windows/pvvxsvc.exe</path>
   </app>
-  <app os='windows' name='rhev-apt'>
-    <path>windows/rhev-apt.exe</path>
+
+  <!-- SUSE Virtual Machine Driver Pack (VMDP) setup program -->
+  <app os='windows' name='vmdp'>
+    <path>windows/VMDP-WIN-2.1.exe</path>
   </app>
 
   <!-- Default file locations -->
diff -Nurp a/v2v/virt-v2v.pl b/v2v/virt-v2v.pl
--- a/v2v/virt-v2v.pl	2014-01-17 10:59:52.587258375 -0700
+++ b/v2v/virt-v2v.pl	2014-01-17 15:50:01.483839535 -0700
@@ -368,6 +368,26 @@ Display a list of target profile names s
 
 =cut
 
+my $vmdp = "auto";
+
+=item B<--vmdp=auto>
+
+=item B<--vmdp=always>
+
+=item B<--vmdp=never>
+
+Specifies when the SUSE Virtual Machine Driver Pack (VMDP) should be installed
+on Windows guests. The default setting is "auto", which causes the VMDP to
+only be installed if the VMDP is already installed on the original guest (for
+Xen PV drivers).
+
+B<N.B.> The VMDP can only be installed during the conversion process if the
+virt-v2v-vmdp RPM has been installed on the virt-v2v host, or if the virtio
+drivers have been manually copied to the correct directory structure under
+/usr/share/virtio-win.
+
+=cut
+
 my $verbose;
 
 =item B<-v | --verbose>
@@ -464,7 +484,8 @@ GetOptions ("help|?"      => sub {
             },
             "root=s"      => \$root_choice,
             "p|profile=s" => \$profile,
-            "list-profiles" => \$list_profiles
+            "list-profiles" => \$list_profiles,
+            "vmdp=s" => \$vmdp
 ) or pod2usage(2);
 
 # Enable higher levels of verbose logging
@@ -669,6 +690,9 @@ my %options;
 if ($output_method eq 'rhev') {
     $options{NO_SERIAL_CONSOLE} = 1;
 }
+if ($vmdp) {
+    $options{VMDP} = $vmdp;
+}
 
 my $guestcaps;
 my $root;