[PATCH] Check a grub kernel exists before selecting it
by Matthew Booth
Handle the case where grub refers to a kernel which doesn't exist by ignoring
that kernel.
---
lib/Sys/VirtV2V/GuestOS/RedHat.pm | 46 +++++++++++++++++-------------------
1 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
index 77d9332..10ff77d 100644
--- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
+++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
@@ -350,39 +350,37 @@ sub get_default_kernel
$default = $g->aug_get('/files/boot/grub/menu.lst/default');
};
+ # Get the grub filesystem
+ my $grub = $self->{desc}->{boot}->{grub_fs};
+
+ # Look for a kernel, starting with the default
+ my @paths;
+ push(@paths, $g->aug_match("/files/boot/grub/menu.lst/".
+ "title[$default]/kernel")) if defined($default);
+ push(@paths, $g->aug_match('/files/boot/grub/menu.lst/title/kernel'));
+
my $kernel;
- if(defined($default)) {
- # Grub's default is zero-based, but augeas arrays are 1-based.
- $default += 1;
+ foreach my $path (@paths) {
+ $kernel = $g->aug_get($path);
- # Check it's got a kernel entry
- eval {
- $kernel =
- $g->aug_get("/files/boot/grub/menu.lst/title[$default]/kernel");
- };
- }
+ # Prepend the grub filesystem to the kernel path
+ $kernel = "$grub$kernel" if(defined($grub));
- # If we didn't find a default, find the first listed kernel
- if(!defined($kernel)) {
- eval {
- my @paths = $g->aug_match('/files/boot/grub/menu.lst/title/kernel');
+ # Prepend the grub filesystem to the kernel path
+ $kernel = "$grub$kernel" if(defined($grub));
- $kernel = $g->aug_get($paths[0]) if(@paths > 0);
- };
+ # Check the kernel exists
+ last if($g->exists($kernel));
+
+ $kernel = undef;
+ print STDERR user_message(__x("WARNING: grub refers to ".
+ "{path}, which doesn't exist."));
}
# If we got here, grub doesn't contain any kernels. Give up.
die(user_message(__"Unable to find a default kernel"))
unless(defined($kernel));
- my $desc = $self->{desc};
-
- # Get the grub filesystem
- my $grub = $desc->{boot}->{grub_fs};
-
- # Prepend the grub filesystem to the kernel path to get an absolute path
- $kernel = "$grub$kernel" if(defined($grub));
-
# Work out it's version number
my $kernel_desc = inspect_linux_kernel ($g, $kernel, 'rpm');
--
1.6.6.1
14 years, 5 months
[PATCH] Config: Check timestamps on directories when rebuilding transfer iso
by Matthew Booth
We don't currently detect if a file with an old timestamp has been moved into a
directory. This fixes that.
---
lib/Sys/VirtV2V/Config.pm | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/lib/Sys/VirtV2V/Config.pm b/lib/Sys/VirtV2V/Config.pm
index 3fff455..bb30dae 100644
--- a/lib/Sys/VirtV2V/Config.pm
+++ b/lib/Sys/VirtV2V/Config.pm
@@ -154,6 +154,7 @@ sub get_transfer_iso
if ($iso_st->mtime > $config_st->mtime) {
my $rebuild = 0;
+ my %dirs;
foreach my $path (keys(%paths)) {
my $path_st = stat($path);
@@ -161,6 +162,19 @@ sub get_transfer_iso
$rebuild = 1;
last;
}
+
+ # Also check if the containing directory has been updated. This
+ # will pick up the case where a file with an old timestamp has
+ # been moved into a directory.
+ my (undef, $dir, undef) = File::Spec->splitpath($path);
+ if (!exists($dirs{$dir})) {
+ my $dir_st = stat($dir);
+ if ($dir_st->mtime > $iso_st->mtime) {
+ $rebuild = 1;
+ last;
+ }
+ $dirs{$dir} = 1;
+ }
}
return $iso_path if (!$rebuild);
--
1.6.6.1
14 years, 5 months
[PATCH] Warn instead of dying if grub refers to non-existent kernel
by Matthew Booth
---
.gnulib | 2 +-
perl/lib/Sys/Guestfs/Lib.pm | 10 ++++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/.gnulib b/.gnulib
index e2843e3..6d28070 160000
--- a/.gnulib
+++ b/.gnulib
@@ -1 +1 @@
-Subproject commit e2843e30e8c2885eb8cbc77e20c4e0f4d562d44d
+Subproject commit 6d28070c3cc7a02107bf66402983b9fe4c6f8f6f
diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm
index b6c4a31..8ec487d 100644
--- a/perl/lib/Sys/Guestfs/Lib.pm
+++ b/perl/lib/Sys/Guestfs/Lib.pm
@@ -1643,8 +1643,14 @@ sub _check_for_kernels
}
$config{cmdline} = join(' ', @args) if(scalar(@args) > 0);
- my $kernel =
- inspect_linux_kernel($g, $path, $os->{package_format});
+ my $kernel;
+ if ($g->exists($path)) {
+ $kernel =
+ inspect_linux_kernel($g, $path, $os->{package_format});
+ } else {
+ warn __x("grub refers to {path}, which doesn't exist\n",
+ path => $path);
+ }
# Check the kernel was recognised
if(defined($kernel)) {
--
1.6.6.1
14 years, 5 months
[PATCH] List all missing dependencies at once
by Matthew Booth
When a conversion requires a file from the config file which isn't present, we
currently die and report which file was missing. If there are many missing
dependencies, using this method to find them all would take multiple runs.
This change attempts to find all missing dependencies in the first run.
---
lib/Sys/VirtV2V/Config.pm | 9 ----
lib/Sys/VirtV2V/GuestOS/RedHat.pm | 83 +++++++++++++++++++++++++++++--------
2 files changed, 65 insertions(+), 27 deletions(-)
diff --git a/lib/Sys/VirtV2V/Config.pm b/lib/Sys/VirtV2V/Config.pm
index 5aa9917..3fff455 100644
--- a/lib/Sys/VirtV2V/Config.pm
+++ b/lib/Sys/VirtV2V/Config.pm
@@ -258,15 +258,6 @@ sub match_app
xml => $app->toString()))) unless (defined($path));
$path = $path->getData();
- my ($pathroot) = $dom->findnodes('/virt-v2v/path-root/text()');
- my $abs = defined($pathroot) ? $pathroot->getData()."/$path" : $path;
-
- die(user_message(__x("Matched local file {path} for {search}. ".
- "However, this file is not available.",
- path => $abs,
- search => _get_app_search($desc, $name, $arch))))
- unless (-r $abs);
-
my @deps;
foreach my $dep ($app->findnodes('dep/text()')) {
push(@deps, $dep->getData());
diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
index 1fd7d14..77d9332 100644
--- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
+++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
@@ -484,12 +484,22 @@ sub add_kernel
return undef;
}
- return undef if ($self->_newer_installed($app));
+ my @missing;
+ if (!$self->{g}->exists($self->_transfer_path($app))) {
+ push(@missing, $app);
+ } else {
+ return undef if ($self->_newer_installed($app));
+ }
my $user_arch = $kernel_arch eq 'i686' ? 'i386' : $kernel_arch;
+ my @deps = $self->_get_deppaths(\@missing, $user_arch, @$depnames);
+
+ # We can't proceed if there are any files missing
+ _die_missing(@missing) if (@missing > 0);
+
# Install any required kernel dependencies
- $self->_install_rpms(1, $self->_get_deppaths($user_arch, @$depnames));
+ $self->_install_rpms(1, @deps);
# Inspect the rpm to work out what kernel version it contains
my $version;
@@ -514,6 +524,15 @@ sub add_kernel
return $version;
}
+sub _die_missing
+{
+ # We can't proceed if there are any files missing
+ die(user_message(__x("Conversion cannot proceed because the following ".
+ "files referenced in the configuration file are ".
+ "required, but missing: {list}",
+ list => join(' ', @_))));
+}
+
# Inspect the guest description to work out what kernel package is in use
# Returns ($kernel_pkg, $kernel_arch)
sub _discover_kernel
@@ -612,13 +631,19 @@ sub add_application
my $config = $self->{config};
my ($app, $deps) = $config->match_app($self->{desc}, $label, $user_arch);
- # Nothing to do if it's already installed
- return if ($self->_newer_installed($app));
+ my @missing;
+ if (!$self->{g}->exists($self->_transfer_path($app))) {
+ push(@missing, $app);
+ } else {
+ return if ($self->_newer_installed($app));
+ }
my @install = ($app);
# Add any dependencies which aren't already installed to the install set
- push(@install, $self->_get_deppaths($user_arch, @$deps));
+ push(@install, $self->_get_deppaths(\@missing, $user_arch, @$deps));
+
+ _die_missing(@missing) if (@missing > 0);
$self->_install_rpms(1, @install);
}
@@ -740,7 +765,7 @@ sub _newer_installed
sub _get_deppaths
{
my $self = shift;
- my ($arch, @apps) = @_;
+ my ($missing, $arch, @apps) = @_;
my $desc = $self->{desc};
my $config = $self->{config};
@@ -749,16 +774,23 @@ sub _get_deppaths
foreach my $app (@apps) {
my ($path, $deps) = $config->match_app($desc, $app, $arch);
- if (!$self->_newer_installed($path)) {
+ my $exists = $self->{g}->exists($self->_transfer_path($path));
+
+ if (!$exists) {
+ push(@$missing, $path);
+ }
+
+ if (!$exists || !$self->_newer_installed($path)) {
$required{$path} = 1;
- foreach my $deppath ($self->_get_deppaths($arch, @$deps)) {
+ foreach my $deppath ($self->_get_deppaths($missing,
+ $arch, @$deps)) {
$required{$deppath} = 1;
}
}
- # For x86_64, also check if there is any i386 version installed. If
- # there is, check if it needs to be upgraded.
+ # For x86_64, also check if there is any i386 or i686 version installed.
+ # If there is, check if it needs to be upgraded.
if ($arch eq 'x86_64') {
$path = undef;
$deps = undef;
@@ -768,18 +800,33 @@ sub _get_deppaths
($path, $deps) = $config->match_app($desc, $app, 'i386');
};
- if (defined($path) && !$self->_newer_installed($path)) {
- my ($name, undef, undef, undef, $arch) =
- $self->_get_nevra($path);
+ if (defined($path)) {
+ if (!$self->{g}->exists($self->_transfer_path($path))) {
+ push(@$missing, $path);
- my @installed = $self->_get_installed($name, $arch);
- if (@installed > 0) {
- $required{$path} = 1;
-
- foreach my $deppath ($self->_get_deppaths('i386', @$deps)) {
+ foreach my $deppath ($self->_get_deppaths($missing,
+ 'i386', @$deps))
+ {
$required{$deppath} = 1;
}
}
+
+ elsif (!$self->_newer_installed($path)) {
+ my ($name, undef, undef, undef, $arch) =
+ $self->_get_nevra($path);
+
+ my @installed = $self->_get_installed($name, $arch);
+
+ if (@installed > 0) {
+ $required{$path} = 1;
+
+ foreach my $deppath
+ ($self->_get_deppaths($missing, 'i386', @$deps))
+ {
+ $required{$deppath} = 1;
+ }
+ }
+ }
}
}
}
--
1.6.6.1
14 years, 5 months
[PATCH] Converter: Don't die if we can't do guest-specific conversion
by Matthew Booth
We currently die with an error message if we can't find a Converter for a
specific guest operating system. However, virt-v2v can still usefully transfer
storage and metadata.
This change turns the error into a (lengthy) warning, and continues with
metadata conversion if guest conversion isn't possible.
---
lib/Sys/VirtV2V/Converter.pm | 21 ++++++++++++++++++---
1 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/lib/Sys/VirtV2V/Converter.pm b/lib/Sys/VirtV2V/Converter.pm
index a5b7e43..97c212e 100644
--- a/lib/Sys/VirtV2V/Converter.pm
+++ b/lib/Sys/VirtV2V/Converter.pm
@@ -136,7 +136,7 @@ sub convert
my $class = shift;
my ($g, $guestos, $config, $dom, $desc, $devices) = @_;
- carp("convert called without guestos argument") unless defined($guestos);
+ # guestos may be undef if none was found
carp("convert called without config argument") unless defined($config);
carp("convert called without dom argument") unless defined($dom);
carp("convert called without desc argument") unless defined($desc);
@@ -152,8 +152,23 @@ sub convert
}
}
- die(user_message(__"Unable to find a module to convert this guest"))
- unless (defined($guestcaps));
+ unless (defined($guestcaps)) {
+ print STDERR user_message(__x("WARNING: Unable to convert this guest ".
+ "operating system. Its storage will be ".
+ "transfered and a domain created for ".
+ "it, but it may not operate correctly ".
+ "without manual reconfiguration. The ".
+ "domain will present all storage ".
+ "devices as IDE, all network interfaces ".
+ "as e1000 and the host as x86_64."));
+
+ # Set some conservative defaults
+ $guestcaps = {
+ 'arch' => 'x86_64',
+ 'virtio' => 0,
+ 'acpi' => 1
+ };
+ }
# Map network names from config
_map_networks($dom, $config);
--
1.6.6.1
14 years, 5 months
[PATCH 1/2] Config: NFC: always create and pass round a Config object
by Matthew Booth
We previously wouldn't create a Config object if no config file was specified.
This change ensures that a Config object is always created, but will do nothing
interesting if there is no config file.
Apart from being slightly cleaner, this allows information provided by Config to
be later supplied from the command line instead.
---
lib/Sys/VirtV2V/Config.pm | 34 ++++++++++++++++++++--------------
lib/Sys/VirtV2V/Converter.pm | 4 ++--
lib/Sys/VirtV2V/GuestOS.pm | 2 +-
lib/Sys/VirtV2V/GuestOS/RedHat.pm | 18 +-----------------
v2v/virt-v2v.pl | 5 ++---
5 files changed, 26 insertions(+), 37 deletions(-)
diff --git a/lib/Sys/VirtV2V/Config.pm b/lib/Sys/VirtV2V/Config.pm
index 57bf24a..50c613c 100644
--- a/lib/Sys/VirtV2V/Config.pm
+++ b/lib/Sys/VirtV2V/Config.pm
@@ -69,6 +69,9 @@ sub new
my $self = {};
bless($self, $class);
+ # No further config required if no config path was specified
+ return $self if (!defined($path));
+
die(user_message(__x("Config file {path} doesn't exist",
path => $path))) unless (-e $path);
@@ -99,6 +102,8 @@ sub get_transfer_iso
my $dom = $self->{dom};
+ return undef unless (defined($dom));
+
# path-root doesn't have to be defined
my ($root) = $dom->findnodes('/virt-v2v/path-root/text()');
$root = $root->getData() if (defined($root));
@@ -175,15 +180,7 @@ sub get_transfer_iso
return $iso_path;
}
-=item get_app_search(desc, name, arch)
-
-Return a string describing what v2v is looking for in the config file. The
-string is intended to be presented to the user to help improve the configuration
-file.
-
-=cut
-
-sub get_app_search
+sub _get_app_search
{
my ($desc, $name, $arch) = @_;
@@ -216,6 +213,10 @@ sub match_app
my $dom = $self->{dom};
+ die(user_message(__x("No config specified. No app match for {search}",
+ search => _get_app_search($desc, $name, $arch))))
+ unless (defined($dom));
+
my $distro = $desc->{distro};
my $major = $desc->{major_version};
my $minor = $desc->{minor_version};
@@ -248,7 +249,7 @@ sub match_app
}
die(user_message(__x("No app in config matches {search}",
- search => get_app_search($desc, $name, $arch))))
+ search => _get_app_search($desc, $name, $arch))))
unless (defined($app));
my %app;
@@ -263,7 +264,7 @@ sub match_app
die(user_message(__x("Matched local file {path} for {search}. ".
"However, this file is not available.",
path => $abs,
- search => get_app_search($desc, $name, $arch))))
+ search => _get_app_search($desc, $name, $arch))))
unless (-r $abs);
my @deps;
@@ -301,9 +302,14 @@ sub map_network
my $self = shift;
my ($oldname, $oldtype) = @_;
- my ($mapping) = $self->{dom}->findnodes
- ("/virt-v2v/network[\@type='$oldtype' and \@name='$oldname']".
- "/network");
+ my $dom = $self->{dom};
+
+ my $mapping;
+ if (defined($dom)) {
+ my ($mapping) = $dom->findnodes
+ ("/virt-v2v/network[\@type='$oldtype' and \@name='$oldname']".
+ "/network");
+ }
unless (defined($mapping)) {
print STDERR user_message(__x("WARNING: No mapping found for ".
diff --git a/lib/Sys/VirtV2V/Converter.pm b/lib/Sys/VirtV2V/Converter.pm
index 45038ee..a5b7e43 100644
--- a/lib/Sys/VirtV2V/Converter.pm
+++ b/lib/Sys/VirtV2V/Converter.pm
@@ -137,7 +137,7 @@ sub convert
my ($g, $guestos, $config, $dom, $desc, $devices) = @_;
carp("convert called without guestos argument") unless defined($guestos);
- # config will be undefined if no config was specified
+ carp("convert called without config argument") unless defined($config);
carp("convert called without dom argument") unless defined($dom);
carp("convert called without desc argument") unless defined($desc);
carp("convert called without devices argument") unless defined($devices);
@@ -156,7 +156,7 @@ sub convert
unless (defined($guestcaps));
# Map network names from config
- _map_networks($dom, $config) if (defined($config));
+ _map_networks($dom, $config);
# Convert the metadata
_convert_metadata($dom, $desc, $devices, $guestcaps);
diff --git a/lib/Sys/VirtV2V/GuestOS.pm b/lib/Sys/VirtV2V/GuestOS.pm
index fea4ba1..e5b1704 100644
--- a/lib/Sys/VirtV2V/GuestOS.pm
+++ b/lib/Sys/VirtV2V/GuestOS.pm
@@ -100,7 +100,7 @@ sub new
defined($g) or carp("instantiate called without g argument");
defined($desc) or carp("instantiate called without desc argument");
defined($dom) or carp("instantiate called without dom argument");
- # config will be undefined if no config was specified
+ defined($config) or carp("instantiate called without config argument");
my $self = {};
diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
index a4680c5..ee074c1 100644
--- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
+++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
@@ -475,17 +475,8 @@ sub add_kernel
eval {
my $desc = $self->{desc};
- my $config = $self->{config};
- unless (defined($config)) {
- my $search = Sys::VirtV2V::Config::get_app_search
- ($desc, $kernel_pkg, $kernel_arch);
- die(user_message(__x("No config specified. No app match for ".
- "{search}",
- search => $search)));
- }
-
($app, $depnames) =
- $config->match_app($desc, $kernel_pkg, $kernel_arch);
+ $self->{config}->match_app($desc, $kernel_pkg, $kernel_arch);
};
# Return undef if we didn't find a kernel
if ($@) {
@@ -619,13 +610,6 @@ sub add_application
my $user_arch = $desc->{arch};
my $config = $self->{config};
- unless (defined($config)) {
- my $search = Sys::VirtV2V::Config::get_app_search($desc, $label,
- $user_arch);
- die(user_message(__x("No config specified. No app match for {search}",
- search => $search)));
- }
-
my ($app, $deps) = $config->match_app($self->{desc}, $label, $user_arch);
# Nothing to do if it's already installed
diff --git a/v2v/virt-v2v.pl b/v2v/virt-v2v.pl
index ea89e48..d9f6bb3 100755
--- a/v2v/virt-v2v.pl
+++ b/v2v/virt-v2v.pl
@@ -217,8 +217,7 @@ GetOptions ("help|?" => sub {
) or pod2usage(2);
# Read the config file if one was given
-my $config;
-$config = Sys::VirtV2V::Config->new($config_file) if defined($config_file);
+my $config = Sys::VirtV2V::Config->new($config_file);
my $target;
if ($output_method eq "libvirt") {
@@ -302,7 +301,7 @@ my $storage = $conn->get_storage_paths();
# Create the transfer iso if required
my $transferiso;
-$transferiso = $config->get_transfer_iso() if (defined($config));
+$transferiso = $config->get_transfer_iso();
if ($output_method eq 'rhev') {
$) = "36 36";
--
1.6.6.1
14 years, 5 months
[PATCH] Config: Don't require all referenced software to be available
by Matthew Booth
Currently virt-v2v attempts to create an iso containing all software referenced
in the config file before starting. If any software isn't available it displays
an error and exits immediately.
With this change it will ignore software which isn't available at iso creation
time. Instead, it will only display an error if the unavailable software is
actually required. This is much kinder to the casual user using the default
configuration file.
---
lib/Sys/VirtV2V/Config.pm | 41 ++++++++++++++++++++++++++++++-----------
1 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/lib/Sys/VirtV2V/Config.pm b/lib/Sys/VirtV2V/Config.pm
index 117b55b..57bf24a 100644
--- a/lib/Sys/VirtV2V/Config.pm
+++ b/lib/Sys/VirtV2V/Config.pm
@@ -107,6 +107,7 @@ sub get_transfer_iso
# config file
# We use a hash here to avoid duplicates
my %path_args;
+ my %paths;
foreach my $path ($dom->findnodes('/virt-v2v/app/path/text()')) {
$path = $path->getData();
@@ -118,12 +119,10 @@ sub get_transfer_iso
$abs = $path;
}
- # Check the referenced path is accessible
- die(user_message(__x("Unable to access {path} referenced in ".
- "the config file",
- path => $path))) unless (-r $abs);
-
- $path_args{"$path=$abs"} = 1;
+ if (-r $abs) {
+ $path_args{"$path=$abs"} = 1;
+ $paths{$abs} = 1;
+ }
}
# Nothing further to do if there are no paths
@@ -140,16 +139,27 @@ sub get_transfer_iso
# Check if the transfer iso exists, and is newer than the config file
if (-e $iso_path) {
my $iso_st = stat($iso_path)
- or die(user_message(__x("Unable to stat iso file {path}: {error}",
+ or die(user_message(__x("Unable to stat {path}: {error}",
path => $iso_path, error => $!)));
my $config_st = stat($self->{path})
- or die(user_message(__x("Unable to stat config file {path}: ".
- "{error}",
+ or die(user_message(__x("Unable to stat {path}: {error}",
path => $self->{path}, error => $!)));
- # Don't need to re-create if the iso file is newer than the config file
- return $iso_path if ($iso_st->mtime > $config_st->mtime);
+ if ($iso_st->mtime > $config_st->mtime) {
+ my $rebuild = 0;
+
+ foreach my $path (keys(%paths)) {
+ my $path_st = stat($path);
+
+ if ($path_st->mtime > $iso_st->mtime) {
+ $rebuild = 1;
+ last;
+ }
+ }
+
+ return $iso_path if (!$rebuild);
+ }
}
# Re-create the transfer iso
@@ -247,6 +257,15 @@ sub match_app
xml => $app->toString()))) unless (defined($path));
$path = $path->getData();
+ my ($pathroot) = $dom->findnodes('/virt-v2v/path-root/text()');
+ my $abs = defined($pathroot) ? $pathroot->getData()."/$path" : $path;
+
+ die(user_message(__x("Matched local file {path} for {search}. ".
+ "However, this file is not available.",
+ path => $abs,
+ search => get_app_search($desc, $name, $arch))))
+ unless (-r $abs);
+
my @deps;
foreach my $dep ($app->findnodes('dep/text()')) {
push(@deps, $dep->getData());
--
1.6.6.1
14 years, 5 months