Matthew Booth
2010-Aug-16 13:53 UTC
[Libguestfs] [PATCH] Install VirtIO storage and network drivers in Windows
Currently when converting a Windows guest we do a minimum installation of the viostor driver, configure the RHEV guest agent and leave RHEV to properly install viostor and all remaining drivers. This works well if RHEV is properly configured and the installation is not interrupted on first boot. However, if the target of the conversion is not RHEV, RHEV is not properly configured, or the first boot installation process is interrupted, for example by the user logging in and interacting with it, this will fail. In this case, in the absence of a correct driver Windows can mis-detect the VirtIO 'SCSI Controller' and configure the wrong driver for it. This will lead to the guest subsequently failing to boot. This patch complements the RHEV-managed process by additionally copying installable versions of the VirtIO storage and network drivers to the guest during conversion, and adding the location of the drivers to the default search path for drivers. This means that Windows will install correct drivers for network and storage if the RHEV process fails, or if the conversion target is not RHEV. --- lib/Sys/VirtV2V/Converter/Windows.pm | 77 ++++++++++++++++++++++++++++++++++ 1 files changed, 77 insertions(+), 0 deletions(-) diff --git a/lib/Sys/VirtV2V/Converter/Windows.pm b/lib/Sys/VirtV2V/Converter/Windows.pm index 1d4c526..f5bf399 100644 --- a/lib/Sys/VirtV2V/Converter/Windows.pm +++ b/lib/Sys/VirtV2V/Converter/Windows.pm @@ -23,6 +23,7 @@ use warnings; use Carp qw(carp); use File::Temp qw(tempdir); use Data::Dumper; +use Encode qw(encode decode); use IO::String; use XML::DOM; use XML::DOM::XPath; @@ -187,6 +188,7 @@ sub _preconvert _upload_files ($g, $tmpdir, $desc, $devices, $config); _add_viostor_to_registry ($g, $tmpdir, $desc, $devices, $config); _add_service_to_registry ($g, $tmpdir, $desc, $devices, $config); + _prepare_virtio_drivers ($g, $tmpdir, $desc, $devices, $config); } # See http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/ @@ -345,6 +347,81 @@ sub _add_service_to_registry $g->upload ($tmpdir . "/system", $system_filename); } +# We copy the VirtIO drivers to a directory on the guest and add this directory +# to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DevicePath so that it will +# be searched automatically when automatically installing drivers. +sub _prepare_virtio_drivers +{ + my $g = shift; + my $tmpdir = shift; + my $desc = shift; + my $devices = shift; + my $config = shift; + + # Copy the target VirtIO drivers to the guest + my $driverdir = File::Spec->catdir($g->case_sensitive_path("/windows"), "Drivers/VirtIO"); + + $g->mkdir_p($driverdir); + + my ($virtio) = $config->match_app ($desc, 'virtio', $desc->{arch}); + $virtio = $config->get_transfer_path($g, $virtio); + + foreach my $src ($g->ls($virtio)) { + my $name = $src; + $src = File::Spec->catfile($virtio); + my $dst = File::Spec->catfile($driverdir, $name); + $g->cp_a($src, $dst); + } + + # Locate and download the SOFTWARE hive + my $sw_local = File::Spec->catfile($tmpdir, 'software'); + my $sw_guest = $g->case_sensitive_path('/windows/system32/config/software'); + + $g->download($sw_guest, $sw_local); + + # Open the registry hive. + my $h = Win::Hivex->open($sw_local, write => 1) + or die "open hive $sw_local: $!"; + + # Find the node \Microsoft\Windows\CurrentVersion + my $node = $h->root(); + foreach ('Microsoft', 'Windows', 'CurrentVersion') { + $node = $h->node_get_child($node, $_); + } + + # Update DevicePath, but leave everything else as is + my @new; + my $append = ';%SystemRoot%\Drivers\VirtIO'; + foreach my $v ($h->node_values($node)) { + my $key = $h->value_key($v); + my ($type, $data) = $h->value_value($v); + + # Decode the string from utf16le to perl native + my $value = decode('UTF-16LE', $data); + + # Append the driver location if it's not there already + if ($key eq 'DevicePath' && index($value, $append) == -1) { + # Remove the explicit trailing NULL + chop($value); + + # Append the new path and a new explicit trailing NULL + $value .= $append."\0"; + + # Re-encode the string back to utf16le + $data = encode('UTF-16LE', $value); + } + + push (@new, { key => $key, t => $type, value => $data }); + } + $h->node_set_values($node, \@new); + + $h->commit(undef); + undef $h; + + # Upload the new registry. + $g->upload($sw_local, $sw_guest); +} + sub _upload_files { my $g = shift; -- 1.7.2.1
Richard W.M. Jones
2010-Aug-16 14:16 UTC
[Libguestfs] [PATCH] Install VirtIO storage and network drivers in Windows
On Mon, Aug 16, 2010 at 02:53:17PM +0100, Matthew Booth wrote:> Currently when converting a Windows guest we do a minimum installation of the > viostor driver, configure the RHEV guest agent and leave RHEV to properly > install viostor and all remaining drivers. This works well if RHEV is properly > configured and the installation is not interrupted on first boot. > > However, if the target of the conversion is not RHEV, RHEV is not properly > configured, or the first boot installation process is interrupted, for > example by the user logging in and interacting with it, this will fail. In this > case, in the absence of a correct driver Windows can mis-detect the VirtIO 'SCSI > Controller' and configure the wrong driver for it. This will lead to the guest > subsequently failing to boot. > > This patch complements the RHEV-managed process by additionally copying > installable versions of the VirtIO storage and network drivers to the guest > during conversion, and adding the location of the drivers to the default search > path for drivers. This means that Windows will install correct drivers for > network and storage if the RHEV process fails, or if the conversion target is > not RHEV. > --- > lib/Sys/VirtV2V/Converter/Windows.pm | 77 ++++++++++++++++++++++++++++++++++ > 1 files changed, 77 insertions(+), 0 deletions(-) > > diff --git a/lib/Sys/VirtV2V/Converter/Windows.pm b/lib/Sys/VirtV2V/Converter/Windows.pm > index 1d4c526..f5bf399 100644 > --- a/lib/Sys/VirtV2V/Converter/Windows.pm > +++ b/lib/Sys/VirtV2V/Converter/Windows.pm > @@ -23,6 +23,7 @@ use warnings; > use Carp qw(carp); > use File::Temp qw(tempdir); > use Data::Dumper; > +use Encode qw(encode decode); > use IO::String; > use XML::DOM; > use XML::DOM::XPath; > @@ -187,6 +188,7 @@ sub _preconvert > _upload_files ($g, $tmpdir, $desc, $devices, $config); > _add_viostor_to_registry ($g, $tmpdir, $desc, $devices, $config); > _add_service_to_registry ($g, $tmpdir, $desc, $devices, $config); > + _prepare_virtio_drivers ($g, $tmpdir, $desc, $devices, $config); > } > > # See http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-windows-vm/ > @@ -345,6 +347,81 @@ sub _add_service_to_registry > $g->upload ($tmpdir . "/system", $system_filename); > } > > +# We copy the VirtIO drivers to a directory on the guest and add this directory > +# to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DevicePath so that it will > +# be searched automatically when automatically installing drivers. > +sub _prepare_virtio_drivers > +{ > + my $g = shift; > + my $tmpdir = shift; > + my $desc = shift; > + my $devices = shift; > + my $config = shift; > + > + # Copy the target VirtIO drivers to the guest > + my $driverdir = File::Spec->catdir($g->case_sensitive_path("/windows"), "Drivers/VirtIO"); > + > + $g->mkdir_p($driverdir); > + > + my ($virtio) = $config->match_app ($desc, 'virtio', $desc->{arch}); > + $virtio = $config->get_transfer_path($g, $virtio); > + > + foreach my $src ($g->ls($virtio)) { > + my $name = $src; > + $src = File::Spec->catfile($virtio); > + my $dst = File::Spec->catfile($driverdir, $name); > + $g->cp_a($src, $dst); > + } > + > + # Locate and download the SOFTWARE hive > + my $sw_local = File::Spec->catfile($tmpdir, 'software'); > + my $sw_guest = $g->case_sensitive_path('/windows/system32/config/software'); > + > + $g->download($sw_guest, $sw_local); > + > + # Open the registry hive. > + my $h = Win::Hivex->open($sw_local, write => 1) > + or die "open hive $sw_local: $!"; > + > + # Find the node \Microsoft\Windows\CurrentVersion > + my $node = $h->root(); > + foreach ('Microsoft', 'Windows', 'CurrentVersion') { > + $node = $h->node_get_child($node, $_); > + } > + > + # Update DevicePath, but leave everything else as is > + my @new; > + my $append = ';%SystemRoot%\Drivers\VirtIO'; > + foreach my $v ($h->node_values($node)) { > + my $key = $h->value_key($v); > + my ($type, $data) = $h->value_value($v); > + > + # Decode the string from utf16le to perl native > + my $value = decode('UTF-16LE', $data); > + > + # Append the driver location if it's not there already > + if ($key eq 'DevicePath' && index($value, $append) == -1) { > + # Remove the explicit trailing NULL > + chop($value); > + > + # Append the new path and a new explicit trailing NULL > + $value .= $append."\0"; > + > + # Re-encode the string back to utf16le > + $data = encode('UTF-16LE', $value); > + } > + > + push (@new, { key => $key, t => $type, value => $data }); > + } > + $h->node_set_values($node, \@new); > + > + $h->commit(undef); > + undef $h; > + > + # Upload the new registry. > + $g->upload($sw_local, $sw_guest); > +} > + > sub _upload_files > { > my $g = shift;As discussed on list, ACK. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/
Apparently Analagous Threads
- [PATCH] Fix a Windows conversion error when C:\Temp exists in the guest
- [PATCH 1/2] Allow absolute paths in virt-v2v.conf
- [PATCH] Fix error in Converter::Windows when there is no transfer iso
- [PATCH] virt-v2v: Default to non-virtio drivers if driver path is missing
- [PATCH v2v] Pre-convert Windows guests.