Before RHN support was added, the only way to install software was by specifying
it in the config file. To configure VirtIO support, Converter::Linux called
add_kernel(). We setup the config file such that the kernel version in there
supported VirtIO, and everything else which needed to be installed was a
dependency of the kernel. This meant that the RHN support had no good way to
determine from configuration what needed to be installed, and at what versions.
Capabilities describe a set of requirements for a feature, which means they can
be used cleanly for both RHN support, and installation from local sources. They
will also allow VirtIO to be configured in RHEL 3 guests by installing the
kmod-virtio package rather than a new kernel, and are intended to be usable for
installing spice.
This change principally adds install_capability to GuestOS::RedHat, replacing
add_kernel. It also adds a new function, install_good_kernel, which will
specifically attempt to install a bootable kernel from any source. It also
refactors the RHN support to make it usable by both these functions, and adds
additional error checking.
---
lib/Sys/VirtV2V/Config.pm | 54 +++
lib/Sys/VirtV2V/Converter/Linux.pm | 80 ++---
lib/Sys/VirtV2V/GuestOS.pm | 30 --
lib/Sys/VirtV2V/GuestOS/RedHat.pm | 816 ++++++++++++++++++++++++------------
v2v/virt-v2v.conf | 104 +++--
v2v/virt-v2v.conf.pod | 160 +++++---
v2v/virt-v2v.pl | 41 +--
7 files changed, 814 insertions(+), 471 deletions(-)
diff --git a/lib/Sys/VirtV2V/Config.pm b/lib/Sys/VirtV2V/Config.pm
index 46ce0c8..776c359 100644
--- a/lib/Sys/VirtV2V/Config.pm
+++ b/lib/Sys/VirtV2V/Config.pm
@@ -262,6 +262,60 @@ sub _match_query
return $query;
}
+=item match_capability
+
+Match a capability from the configuration. Returned as a hashref containing
+dependencies, where each dependency is a hashref containing:
+
+ {capability} ->
+ {name} -> : package name
+ {minversion} : minimum required version
+ {ifinstalled} : 1 if the package should be upgraded if necessary, but
+ not installed if it is not already, 0 otherwise
+
+Returns undef if the capability was not found.
+
+=cut
+
+sub match_capability
+{
+ my $self = shift;
+ my ($desc, $name, $arch) = @_;
+
+ my $cap = $self->_match_element('capability', $desc, $name, $arch);
+
+ my %out;
+ foreach my $dep ($cap->findnodes('dep')) {
+ my %props;
+ foreach my $prop ('name', 'minversion') {
+ my ($val) = $dep->findnodes('(a)'.$prop);
+ $val &&= $val->getData();
+ die(user_message(__x("Capability in config contains a dependency
".
+ "with no {property} attribute: {xml}",
+ property => $prop,
+ xml => $cap->toString())))
+ if (!defined($val));
+ $props{$prop} = $val;
+ }
+
+ my ($ifinstalled) = $dep->findnodes('@ifinstalled');
+ $ifinstalled &&= $ifinstalled->getData();
+ if (defined($ifinstalled) &&
+ ($ifinstalled eq "1" || $ifinstalled eq "yes"))
+ {
+ $props{ifinstalled} = 1;
+ } else {
+ $props{ifinstalled} = 0;
+ }
+
+ my $depname = $props{name};
+ delete($props{name});
+
+ $out{$depname} = \%props;
+ }
+ return \%out;
+}
+
sub _match_element
{
my $self = shift;
diff --git a/lib/Sys/VirtV2V/Converter/Linux.pm b/lib/Sys/VirtV2V/Converter/Linux.pm
index 3bcba9f..768a3ab 100644
--- a/lib/Sys/VirtV2V/Converter/Linux.pm
+++ b/lib/Sys/VirtV2V/Converter/Linux.pm
@@ -105,11 +105,11 @@ sub convert
# replacement
_unconfigure_hv($g, $guestos, $desc);
- # Get the best available kernel
- my $kernel = _configure_kernel($guestos, $desc);
+ # Try to install the virtio capability
+ my $virtio = $guestos->install_capability('virtio');
- # Check if the resulting kernel will support virtio
- my $virtio = $guestos->supports_virtio($kernel);
+ # Get an appropriate kernel, and remove non-bootable kernels
+ my $kernel = _configure_kernel($guestos, $desc, $virtio);
# Configure the rest of the system
_configure_console($g);
@@ -248,72 +248,45 @@ sub _configure_display_driver
sub _configure_kernel
{
- my ($guestos, $desc) = @_;
-
- my %kernels;
-
- # Look for installed kernels with virtio support
- foreach my $kernel (@{$desc->{kernels}}) {
- my %checklist = (
- "virtio_blk" => undef,
- "virtio_pci" => undef,
- "virtio_net" => undef
- );
-
- foreach my $module (@{$kernel->{modules}}) {
- if(exists($checklist{$module})) {
- $checklist{$module} = 1;
- }
- }
-
- my $virtio = 1;
- foreach my $module (keys(%checklist)) {
- if(!defined($checklist{$module})) {
- $virtio = 0;
- last;
- }
- }
-
- if($virtio) {
- $kernels{$kernel->{version}} = 1;
- } else {
- $kernels{$kernel->{version}} = 0;
- }
- }
+ my ($guestos, $desc, $virtio) = @_;
my @remove_kernels = ();
# Remove foreign hypervisor specific kernels from the list of available
# kernels
foreach my $kernel (_find_hv_kernels($desc)) {
- # Remove the kernel from our cache
- delete($kernels{$kernel});
-
# Don't actually try to remove them yet in case we remove them all. This
- # would make your dependency checker unhappy.
+ # might make your dependency checker unhappy.
push(@remove_kernels, $kernel);
}
- # Find the highest versioned, virtio capable, installed kernel
+ # Pick first appropriate kernel returned by list_kernels()
my $boot_kernel;
- foreach my $kernel (sort {$b cmp $a} (keys(%kernels))) {
- if($kernels{$kernel}) {
- $boot_kernel = $kernel;
- last;
- }
+ foreach my $kernel ($guestos->list_kernels()) {
+ # Skip kernels we're going to remove
+ next if (grep(/^$kernel$/, @remove_kernels));
+
+ # If we're configuring virtio, check this kernel supports it
+ next if ($virtio && !$guestos->supports_virtio($kernel));
+
+ $boot_kernel = $kernel;
+ last;
}
+ # There should be an installed virtio capable kernel if virtio was installed
+ die("virtio configured, but no virtio kernel found")
+ if ($virtio && !defined($boot_kernel));
+
# If none of the installed kernels are appropriate, install a new one
if(!defined($boot_kernel)) {
- $boot_kernel = $guestos->add_kernel();
+ $boot_kernel = $guestos->install_good_kernel();
}
- # Check that either there are still kernels in the cache, or we just added a
- # kernel. If neither of these is the case, we're about to try to remove all
- # kernels, which will fail unpleasantly. Fail nicely instead.
+ # Check we have a bootable kernel. If we don't, we're probably about to
+ # remove all kernels, which will fail unpleasantly. Fail nicely instead.
die(user_message(__"No bootable kernels installed, and no replacement ".
- "specified in configuration.\nUnable to continue."))
- unless(keys(%kernels) > 0 || defined($boot_kernel));
+ "is available.\nUnable to continue."))
+ unless(defined($boot_kernel));
# It's safe to remove kernels now
foreach my $kernel (@remove_kernels) {
@@ -321,9 +294,6 @@ sub _configure_kernel
$guestos->remove_kernel($kernel);
}
- # If we didn't install a new kernel, pick the default kernel
- $boot_kernel ||= $guestos->get_default_kernel();
-
return $boot_kernel;
}
diff --git a/lib/Sys/VirtV2V/GuestOS.pm b/lib/Sys/VirtV2V/GuestOS.pm
index 7d3f1c7..57311ec 100644
--- a/lib/Sys/VirtV2V/GuestOS.pm
+++ b/lib/Sys/VirtV2V/GuestOS.pm
@@ -242,23 +242,6 @@ The name of the new disply driver. An example is I<cirrus>.
Update the display driver, if defined, to the given driver.
-=item get_default_kernel
-
-get_default_kernel returns the version number of the kernel which will be booted
-according to the current configuration. It examines the guest directly rather
-than relying on the output from Sys::Guestfs::Lib, which may be out of date.
-
-=item add_kernel
-
-add_kernel installs a new kernel. It chooses a kernel label based on the name of
-the default kernel installed in the guest. See L<virt-v2v(5)> for details of how
-files are selected for installation.
-
-add_kernel will also install dependencies of the chosen kernel.
-
-add_kernel returns the version number of the kernel it installed, or undef if it
-did not find a kernel to install.
-
=item remove_kernel(version)
=over
@@ -271,19 +254,6 @@ The version number of the kernel to be removed.
remove_kernel uninstalls a kernel from the guest.
-=item remove_application(name)
-
-=over
-
-=item name
-
-The name of the the application, as it is known to the underlying package
-manager.
-
-=back
-
-remove an application from the guest.
-
=item get_application_owner(file)
=over
diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
index a5dc1cc..99dcb12 100644
--- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
+++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
@@ -399,13 +399,14 @@ sub _check_augeas_device
return $augeas;
}
-=item get_default_kernel()
+=item list_kernels()
-See BACKEND INTERFACE in L<Sys::VirtV2V::GuestOS> for details.
+List all installed kernels. List the default kernel first, followed by the
+remaining kernels in the order they are listed in grub.
=cut
-sub get_default_kernel
+sub list_kernels
{
my $self = shift;
@@ -429,11 +430,15 @@ sub get_default_kernel
if defined($default);
push(@paths,
$g->aug_match('/files/boot/grub/menu.lst/title/kernel'));
};
-
$self->_augeas_error($@) if ($@);
- my $kernel;
+ my @kernels;
+ my %checked;
foreach my $path (@paths) {
+ next if ($checked{$path});
+ $checked{$path} = 1;
+
+ my $kernel;
eval {
$kernel = $g->aug_get($path);
};
@@ -443,249 +448,628 @@ sub get_default_kernel
$kernel = "$grub$kernel" if(defined($grub));
# Check the kernel exists
- last if($g->exists($kernel));
+ if ($g->exists($kernel)) {
+ # Work out it's version number
+ my $kernel_desc = inspect_linux_kernel($g, $kernel, 'rpm');
- print STDERR user_message(__x("WARNING: grub refers to ".
- "{path}, which doesn't exist.",
- path => $kernel));
- $kernel = undef;
+ push(@kernels, $kernel_desc->{version});
+ }
+
+ else {
+ warn user_message(__x("WARNING: grub refers to {path}, which ".
+ "doesn't exist.",
+ path => $kernel));
+ }
}
- # If we got here, grub doesn't contain any kernels. Give up.
- die(user_message(__"Unable to find a default kernel"))
- unless(defined($kernel));
+ return @kernels;
+}
- # Work out it's version number
- my $kernel_desc = inspect_linux_kernel ($g, $kernel, 'rpm');
+sub _parse_evr
+{
+ my ($evr) = @_;
+
+ $evr =~ /^(?:(\d+):)?([^-]+)(?:-(\S+))?$/ or die();
- return $kernel_desc->{version};
+ my $epoch = $1;
+ my $version = $2;
+ my $release = $3;
+
+ return ($epoch, $version, $release);
}
-=item add_kernel()
+=item install_capability(name)
-See BACKEND INTERFACE in L<Sys::VirtV2V::GuestOS> for details.
+Install a capability specified in the configuration file.
=cut
-sub add_kernel
+sub install_capability
{
my $self = shift;
+ my ($name) = @_;
- my ($kernel_pkg, $kernel_ver, $kernel_arch) = $self->_discover_kernel();
+ my $desc = $self->{desc};
+ my $config = $self->{config};
- # If the guest is using a Xen PV kernel, choose an appropriate normal kernel
- # replacement
- if ($kernel_pkg eq "kernel-xen" || $kernel_pkg eq "kernel-xenU")
{
- my $desc = $self->{desc};
-
- # Make an informed choice about a replacement kernel for distros we know
- # about
-
- # RHEL 5
- if ($desc->{distro} eq 'rhel' && $desc->{major_version} eq
'5') {
- if ($kernel_arch eq 'i686') {
- # XXX: This assumes that PAE will be available in the
- # hypervisor. While this is almost certainly true, it's
- # theoretically possible that it isn't. The information we need
- # is available in the capabilities XML.
- # If PAE isn't available, we should choose 'kernel'.
- $kernel_pkg = 'kernel-PAE';
- }
+ my $cap;
+ eval {
+ $cap = $config->match_capability($desc, $name);
+ };
+ if ($@) {
+ warn($@);
+ return 0;
+ }
- # There's only 1 kernel package on RHEL 5 x86_64
- else {
- $kernel_pkg = 'kernel';
- }
- }
+ if (!defined($cap)) {
+ warn(user_message(__x("{name} capability not found in configuration",
+ name => $name)));
+ return 0;
+ }
- # RHEL 4
- elsif ($desc->{distro} eq 'rhel' && $desc->{major_version}
eq '4') {
- my $ncpus = $self->get_ncpus();
+ my @install;
+ my @upgrade;
+ my $kernel;
+ foreach my $name (keys(%$cap)) {
+ my $props = $cap->{$name};
+ my $ifinstalled = $props->{ifinstalled};
- if ($kernel_arch eq 'i686') {
- # If the guest has > 10G RAM, give it a hugemem kernel
- if ($self->get_memory_kb() > 10 * 1024 * 1024) {
- $kernel_pkg = 'kernel-hugemem';
- }
+ # Parse epoch, version and release from minversion
+ my ($min_epoch, $min_version, $min_release);
+ eval {
+ ($min_epoch, $min_version, $min_release) =
+ _parse_evr($props->{minversion});
+ };
+ if ($@) {
+ die(user_message(__x("Unrecognised format for {field} in config:
".
+ "{value}. {field} must be in the format ".
+ "[epoch:]version[-release].",
+ field => 'minversion',
+ value => $props->{minversion})));
+ }
- # SMP kernel for guests with >1 CPU
- elsif ($ncpus > 1) {
- $kernel_pkg = 'kernel-smp';
- }
+ # Kernels are special
+ if ($name eq 'kernel') {
+ my ($kernel_pkg, $kernel_rpmver, $kernel_arch) =
+ $self->_discover_kernel();
- else {
- $kernel_pkg = 'kernel';
- }
+ my ($kernel_epoch, $kernel_ver, $kernel_release);
+ eval {
+ ($kernel_epoch, $kernel_ver, $kernel_release) =
+ _parse_evr($kernel_rpmver);
+ };
+ if ($@) {
+ # Don't die here, just make best effort to do a version
+ # comparison by directly comparing the full strings
+ $kernel_epoch = undef;
+ $kernel_ver = $kernel_rpmver;
+ $kernel_release = undef;
+
+ $min_epoch = undef;
+ $min_version = $props->{minversion};
+ $min_release = undef;
}
- else {
- if ($ncpus > 8) {
- $kernel_pkg = 'kernel-largesmp';
+ # If the guest is using a Xen PV kernel, choose an appropriate
+ # normal kernel replacement
+ if ($kernel_pkg eq "kernel-xen" || $kernel_pkg eq
"kernel-xenU") {
+ $kernel_pkg = $self->_get_replacement_kernel_name($kernel_arch);
+
+ # filter out xen/xenU from release field
+ if (defined($kernel_release) &&
+ $kernel_release =~ /^(\S+?)(xen)?(U)?$/)
+ {
+ $kernel_release = $1;
}
- elsif ($ncpus > 1) {
- $kernel_pkg = 'kernel-smp';
+ # If the guest kernel is new enough, but PV, try to replace it
+ # with an equivalent version FV kernel
+ if (_evr_cmp($kernel_epoch, $kernel_ver, $kernel_release,
+ $min_epoch, $min_version, $min_release) >= 0) {
+ $kernel = [$kernel_pkg, $kernel_arch,
+ $kernel_epoch, $kernel_ver, $kernel_release];
}
+ # Otherwise, just grab the latest
else {
- $kernel_pkg = 'kernel';
+ $kernel = [$kernel_pkg, $kernel_arch];
}
}
+
+ # If the kernel is too old, grab the latest replacement
+ elsif (_evr_cmp($kernel_epoch, $kernel_ver, $kernel_release,
+ $min_epoch, $min_version, $min_release) < 0) {
+ $kernel = [$kernel_pkg, $kernel_arch];
+ }
}
- # RHEL 3 didn't have a xen kernel
+ else {
+ my @installed = $self->_get_installed($name);
+
+ # Ignore an 'ifinstalled' dep if it's not currently installed
+ next if (@installed == 0 && $ifinstalled);
- # XXX: Could do with a history of Fedora kernels in here
+ # Check if any installed version meets the minimum version
+ my $found = 0;
+ foreach my $app (@installed) {
+ my ($epoch, $version, $release) = @$app;
- # For other distros, be conservative and just return 'kernel'
- else {
- $kernel_pkg = 'kernel';
+ if (_evr_cmp($app->[0], $app->[1], $app->[2],
+ $min_epoch, $min_version, $min_release) >= 0) {
+ $found = 1;
+ last;
+ }
+ }
+
+ # Install the latest available version of the dep if it wasn't found
+ if (!$found) {
+ if (@installed == 0) {
+ push(@install, [$name]);
+ } else {
+ push(@upgrade, [$name]);
+ }
+ }
}
}
- my $version;
+ # Capability is already installed
+ if (!defined($kernel) && @install == 0 && @upgrade == 0) {
+ return 1;
+ }
+
my $g = $self->{g};
- my $update_fail = 0;
- # try using up2date / yum if available
- if ($g->exists('/usr/sbin/up2date') or
$g->exists('/usr/bin/yum')) {
+ # List of kernels before the new kernel installation
+ my @k_before = $g->glob_expand('/boot/vmlinuz-*');
+
+ my $success = $self->_install_any($kernel, \@install, \@upgrade);
+
+ # Check to see if we installed a new kernel, and check grub if we did
+ $self->_find_new_kernel(@k_before);
+
+ return $success;
+}
+
+sub _get_replacement_kernel_name
+{
+ my $self = shift;
+ my ($arch) = @_;
- my $desc = $self->{desc};
+ my $desc = $self->{desc};
- my ($min_virtio_ver, @kern_vr, @preinst_cmd, @inst_cmd, $inst_fmt);
+ # Make an informed choice about a replacement kernel for distros we know
+ # about
+
+ # RHEL 5
+ if ($desc->{distro} eq 'rhel' && $desc->{major_version} eq
'5') {
+ if ($arch eq 'i686') {
+ # XXX: This assumes that PAE will be available in the hypervisor.
+ # While this is almost certainly true, it's theoretically possible
+ # that it isn't. The information we need is available in the
+ # capabilities XML. If PAE isn't available, we should choose
+ # 'kernel'.
+ return 'kernel-PAE';
+ }
- # filter out xen/xenU from release field
- if ($kernel_ver =~ /^(\S+)-(\S+?)(xen)?(U)?$/) {
- @kern_vr = ($1, $2);
- $kernel_ver = join('-', @kern_vr);
+ # There's only 1 kernel package on RHEL 5 x86_64
+ else {
+ return 'kernel';
}
+ }
- # We need to upgrade kernel deps. first to avoid possible conflicts
- my $deps = ($self->{config}->match_app($desc, $kernel_pkg,
$kernel_arch))[1];
-
- # use up2date when available (RHEL-4 and earlier)
- if ($g->exists('/usr/sbin/up2date')) {
- if (_rpmvercmp($kernel_ver, '2.6.9-89.EL') >= 0) {
- # Install matching kernel version
- @inst_cmd = ('/usr/bin/python', '-c',
- "import sys; sys.path.append('/usr/share/rhn');" .
- "import actions.packages;" .
- "actions.packages.cfg['forceInstall'] = 1;" .
- "actions.packages.update([['$kernel_pkg', " .
- "'$kern_vr[0]', '$kern_vr[1]',
'']])");
- } else {
- # Install latest available kernel version
- @inst_cmd = ('/usr/sbin/up2date', '-fi', $kernel_pkg);
+ # RHEL 4
+ elsif ($desc->{distro} eq 'rhel' && $desc->{major_version} eq
'4') {
+ my $ncpus = $self->get_ncpus();
+
+ if ($arch eq 'i686') {
+ # If the guest has > 10G RAM, give it a hugemem kernel
+ if ($self->get_memory_kb() > 10 * 1024 * 1024) {
+ return 'kernel-hugemem';
}
- if (@$deps) {
- use Data::Dumper; print Dumper($deps);
- @preinst_cmd = ('/usr/sbin/up2date', '-fu', @$deps);
+ # SMP kernel for guests with >1 CPU
+ elsif ($ncpus > 1) {
+ return 'kernel-smp';
+ }
+
+ else {
+ return 'kernel';
}
}
- # use yum when available (RHEL-5 and beyond)
- elsif ($g->exists('/usr/bin/yum')) {
- if (_rpmvercmp($kernel_ver, '2.6.18-128.el5') >= 0) {
- # Install matching kernel version
- @inst_cmd = ('/usr/bin/yum', '-y', 'install',
- "$kernel_pkg-$kernel_ver");
- } else {
- # Install latest available kernel version
- @inst_cmd = ('/usr/bin/yum', '-y', 'install',
$kernel_pkg);
+
+ else {
+ if ($ncpus > 8) {
+ return 'kernel-largesmp';
+ }
+
+ elsif ($ncpus > 1) {
+ return 'kernel-smp';
}
- if ($deps) {
- @preinst_cmd = ('/usr/bin/yum', '-y', 'upgrade',
@$deps);
+ else {
+ return 'kernel';
}
}
+ }
- my (@k_before, @k_new);
+ # RHEL 3 didn't have a xen kernel
- # List of kernels before the new kernel installation
- @k_before = $self->{g}->glob_expand('/boot/vmlinuz-*');
+ # XXX: Could do with a history of Fedora kernels in here
- eval {
- # Upgrade dependencies if needed
- if (@preinst_cmd) {
- $g->command(\@preinst_cmd);
- }
- # Install new kernel
- $g->command(\@inst_cmd);
- };
+ # For other distros, be conservative and just return 'kernel'
+ return 'kernel';
+}
- if ($@) {
- $update_fail = 1;
+sub _install_any
+{
+ my $self = shift;
+ my ($kernel, $install, $upgrade) = @_;
+
+ my $g = $self->{g};
+
+ my $resolv_bak = $g->exists('/etc/resolv.conf');
+ $g->mv('/etc/resolv.conf', '/etc/resolv.conf.v2vtmp') if
($resolv_bak);
+
+ # XXX We should get the nameserver from the appliance here. However,
+ # there's no current api other than debug to do this, and in any case
+ # resolv.conf in the appliance is both hardcoded and currently wrong.
+ $g->write_file('/etc/resolv.conf', "nameserver 169.254.2.3",
0);
+
+ my $success;
+ eval {
+ # Try to fetch these dependencies using the guest's native update tool
+ $success = $self->_install_up2date($kernel, $install, $upgrade);
+ $success = $self->_install_yum($kernel, $install, $upgrade)
+ unless ($success);
+
+ # Fall back to local config if the above didn't work
+ $success = $self->_install_config($kernel, $install, $upgrade)
+ unless ($success);
+ };
+ if ($@) {
+ warn($@);
+ $success = 0;
+ }
+
+ $g->mv('/etc/resolv.conf.v2vtmp', '/etc/resolv.conf') if
($resolv_bak);
+
+ # Make augeas reload to pick up any altered configuration
+ eval {
+ $g->aug_load();
+ };
+ $self->_augeas_error($@) if ($@);
+
+ return $success;
+}
+
+sub _install_up2date
+{
+ my $self = shift;
+ my ($kernel, $install, $upgrade) = @_;
+
+ my $g = $self->{g};
+
+ # Check this system has actions.packages
+ return 0 unless ($g->exists('/usr/bin/up2date'));
+
+ # Check this system is registered to rhn
+ return 0 unless ($g->exists('/etc/sysconfig/rhn/systemid'));
+
+ my @pkgs;
+ foreach my $pkg ($kernel, @$install, @$upgrade) {
+ next unless defined($pkg);
+
+ # up2date doesn't do arch
+ my ($name, undef, $epoch, $version, $release) = @$pkg;
+
+ $epoch ||= "";
+ $version ||= "";
+ $release ||= "";
+
+ push(@pkgs, "['$name', '$version', '$release',
'$epoch']");
+ }
+
+ eval {
+ $g->command(['/usr/bin/python', '-c',
+ "import sys; sys.path.append('/usr/share/rhn');
".
+ "import actions.packages; ".
+ "actions.packages.cfg['forceInstall'] = 1;
".
+ "ret = actions.packages.update([".join(',',
@pkgs)."]); ".
+ "sys.exit(ret[0]); "]);
+ };
+ if ($@) {
+ warn(user_message(__x("Failed to install packages using up2date. ".
+ "Error message was: {error}",
+ error => $@)));
+ return 0;
+ }
+
+ return 1;
+}
+
+sub _install_yum
+{
+ my $self = shift;
+ my ($kernel, $install, $upgrade) = @_;
+
+ my $g = $self->{g};
+
+ # Check this system has yum installed
+ return 0 unless ($g->exists('/usr/bin/yum'));
+
+ # Install or upgrade the kernel?
+ # If it isn't installed (because we're replacing a PV kernel), we need to
+ # install
+ # If we're installing a specific version, we need to install
+ # If the kernel package we're installing is already installed and we're
+ # just upgrading to the latest version, we need to upgrade
+ if (defined($kernel)) {
+ my @installed = $self->_get_installed($kernel->[0]);
+
+ # Don't modify the contents of $install and $upgrade in case we fall
+ # through and they're reused in another function
+ if (@installed == 0 || defined($kernel->[2])) {
+ my @tmp = @$install;
+ push(@tmp, $kernel);
+ $install = \@tmp;
+ } else {
+ my @tmp = @$upgrade;
+ push(@tmp, $kernel);
+ $upgrade = \@tmp;
}
- else {
+ }
+
+ my $success = 1;
+ YUM: foreach my $task (
+ [ "install", $install, qr/(^No package|already installed)/ ],
+ [ "upgrade", $upgrade, qr/^No Packages/ ]
+ ) {
+ my ($action, $list, $failure) = @$task;
+
+ # We can't do these all in a single transaction, because yum offers us
+ # no way to tell if a transaction partially succeeded
+ foreach my $entry (@$list) {
+ next unless (defined($entry));
- # Figure out which kernel has just been installed
- foreach my $k ($g->glob_expand('/boot/vmlinuz-*')) {
- grep(/^$k$/, @k_before) or push(@k_new, $k);
+ # You can't specify epoch without architecture to yum, so we just
+ # ignore epoch and hope
+ my ($name, undef, undef, $version, $release) = @$entry;
+
+ # Construct n-v-r
+ my $pkg = $name;
+ $pkg .= "-$version" if (defined($version));
+ $pkg .= "-$release" if (defined($release));
+
+ my @output;
+ eval {
+ @output = $g->sh_lines("LANG=C /usr/bin/yum -y $action
$pkg");
+ };
+ if ($@) {
+ warn(user_message(__x("Failed to install packages using yum.
".
+ "Output was: {output}",
+ error => $@)));
+ $success = 0;
+ last YUM;
}
- # version-release of the new kernel package
- $version = ($g->command_lines(
- ['rpm', '-qf', '--qf=%{VERSION}-%{RELEASE}',
$k_new[0]]))[0];
+ foreach my $line (@output) {
+ # Yum probably just isn't configured. Don't bother with an error
+ # message
+ if ($line =~ /$failure/) {
+ $success = 0;
+ last YUM;
+ }
+ }
}
}
- if ($update_fail) {
+ return $success;
+}
- my ($app, $depnames);
- eval {
- my $desc = $self->{desc};
+sub _install_config
+{
+ my $self = shift;
+ my ($kernel_naevr, $install, $upgrade) = @_;
- ($app, $depnames) =
- $self->{config}->match_app($desc, $kernel_pkg, $kernel_arch);
- };
- # Return undef if we didn't find a kernel
- if ($@) {
- print STDERR $@;
- return undef;
- }
+ my $g = $self->{g};
+ my $desc = $self->{desc};
- my @missing;
- if (!$g->exists($self->_transfer_path($app))) {
- push(@missing, $app);
- } else {
- return undef if ($self->_newer_installed($app));
- }
+ my ($kernel, $user);
+ if (defined($kernel_naevr)) {
+ my ($kernel_pkg, $kernel_arch) = @$kernel_naevr;
- my $user_arch = $kernel_arch eq 'i686' ? 'i386' : $kernel_arch;
+ ($kernel, $user) =
+ $self->{config}->match_app($desc, $kernel_pkg, $kernel_arch);
+ } else {
+ $user = [];
+ }
+
+ foreach my $pkg (@$install, @$upgrade) {
+ push(@$user, $pkg->[0]);
+ }
- my @deps = $self->_get_deppaths(\@missing, $user_arch, @$depnames);
+ my @missing;
+ if (defined($kernel) && !$g->exists($self->_transfer_path($kernel))) {
+ push(@missing, $kernel);
+ }
- # We can't proceed if there are any files missing
- _die_missing(@missing) if (@missing > 0);
+ my @user_paths = $self->_get_deppaths(\@missing, $desc->{arch}, @$user);
- # Install any required kernel dependencies
- $self->_install_rpms(1, @deps);
+ # We can't proceed if there are any files missing
+ _die_missing(@missing) if (@missing > 0);
- # Inspect the rpm to work out what kernel version it contains
- foreach my $file ($g->command_lines
- (["rpm", "-qlp", $self->_transfer_path($app)]))
- {
- if($file =~ m{^/boot/vmlinuz-(.*)$}) {
- $version = $1;
- last;
+ # Install any non-kernel requirements
+ $self->_install_rpms(1, @user_paths);
+
+ if (defined($kernel)) {
+ $self->_install_rpms(0, ($kernel));
+ }
+
+ return 1;
+}
+
+=item install_good_kernel
+
+Attempt to install a known-good kernel
+
+=cut
+
+sub install_good_kernel
+{
+ my $self = shift;
+
+ my $g = $self->{g};
+
+ my ($kernel_pkg, $kernel_rpmver, $kernel_arch) = $self->_discover_kernel();
+
+ # If the guest is using a Xen PV kernel, choose an appropriate
+ # normal kernel replacement
+ if ($kernel_pkg eq "kernel-xen" || $kernel_pkg eq "kernel-xenU")
{
+ $kernel_pkg = $self->_get_replacement_kernel_name($kernel_arch);
+ }
+
+ # List of kernels before the new kernel installation
+ my @k_before = $g->glob_expand('/boot/vmlinuz-*');
+
+ return undef unless ($self->_install_any([$kernel_pkg, $kernel_arch]));
+
+ my $version = $self->_find_new_kernel(@k_before);
+ die("Couldn't determine version of installed kernel")
+ unless (defined($version));
+
+ return $version;
+}
+
+sub _find_new_kernel
+{
+ my $self = shift;
+
+ my $g = $self->{g};
+
+ # Figure out which kernel has just been installed
+ foreach my $k ($g->glob_expand('/boot/vmlinuz-*')) {
+ if (!grep(/^$k$/, @_)) {
+ # Check which directory in /lib/modules the kernel rpm creates
+ foreach my $file ($g->command_lines (['rpm', '-qlf', $k]))
{
+ next unless ($file =~ m{^/lib/modules/([^/]+)$});
+
+ my $version = $1;
+ if ($g->is_dir("/lib/modules/$version")) {
+ $self->_check_grub($version, $k);
+ return $version;
+ }
}
}
+ }
+ return undef;
+}
- die(user_message(__x("{path} doesn't contain a valid kernel",
- path => $app))) if(!defined($version));
+# grubby can sometimes fail to correctly update grub.conf when run from
+# libguestfs. If it looks like this happened, install a new grub config here.
+sub _check_grub
+{
+ my $self = shift;
+ my ($version, $kernel) = @_;
- $self->_install_rpms(0, ($app));
+ my $g = $self->{g};
+ # Nothing to do if there's already a grub entry
+ eval {
+ foreach my $augpath
+ ($g->aug_match('/files/boot/grub/menu.lst/title/kernel'))
+ {
+ return if ($g->aug_get($augpath) eq $kernel);
+ }
+ };
+ $self->_augeas_error($@) if ($@);
+
+ my $prefix;
+ if ($self->{desc}->{boot}->{grub_fs} eq "/boot") {
+ $prefix = '';
+ } else {
+ $prefix = '/boot';
}
- # Make augeas reload so it'll find the new kernel
+ my $initrd = "$prefix/initrd-$version.img";
+ $kernel =~ m{^/boot/(.*)$} or die("kernel in unexpected location:
$kernel");
+ my $vmlinuz = "$prefix/$1";
+
+ my $title;
+ # No point in dying if /etc/redhat-release can't be read
eval {
- $g->aug_load();
+ ($title) = $g->read_lines('/etc/redhat-release');
};
+ $title ||= 'Linux';
- $self->_augeas_error($@) if ($@);
+ # This is how new-kernel-pkg does it
+ $title =~ s/ release.*//;
+ $title .= " ($version)";
- return $version;
+ my $default;
+ # Doesn't matter if there's no default
+ eval {
+ $default = $g->aug_get('/files/boot/grub/menu.lst/default');
+ };
+
+ eval {
+ if (defined($default)) {
+ $g->aug_defvar('template',
+ '/files/boot/grub/menu.lst/title['.($default + 1).']');
+ }
+
+ # If there's no default, take the first entry with a kernel
+ else {
+ my ($match) =
+ $g->aug_match('/files/boot/grub/menu.lst/title/kernel');
+
+ die("No template kernel found in grub") unless(defined($match));
+
+ $match =~ s/\/kernel$//;
+ $g->aug_defvar('template', $match);
+ }
+
+ # Add a new title node at the end
+ $g->aug_defnode('new',
+ '/files/boot/grub/menu.lst/title[last()+1]',
+ $title);
+
+ # N.B. Don't change the order of root, kernel and initrd below, or the
+ # guest will not boot.
+
+ # Copy root from the template
+ $g->aug_set('$new/root', $g->aug_get('$template/root'));
+
+ # Set kernel and initrd to the new values
+ $g->aug_set('$new/kernel', $vmlinuz);
+ $g->aug_set('$new/initrd', $initrd);
+
+ # Copy all kernel command-line arguments
+ foreach my $arg ($g->aug_match('$template/kernel/*')) {
+ # kernel arguments don't necessarily have values
+ my $val;
+ eval {
+ $val = $g->aug_get($arg);
+ };
+
+ $arg =~ /([^\/]*)$/;
+ $arg = $1;
+
+ if (defined($val)) {
+ $g->aug_set('$new/kernel/'.$arg, $val);
+ } else {
+ $g->aug_clear('$new/kernel/'.$arg);
+ }
+ }
+
+ my ($new) = $g->aug_match('$new');
+ $new =~ /\[(\d+)\]$/;
+
+ $g->aug_set('/files/boot/grub/menu.lst/default',
+ defined($1) ? $1 - 1 : 0);
+
+ $g->aug_save();
+ };
+ $self->_augeas_error($@) if ($@);
}
sub _die_missing
@@ -809,12 +1193,12 @@ sub _get_nevra
sub _get_installed
{
my $self = shift;
- my ($name, $arch) = @_;
+ my ($name) = @_;
my $g = $self->{g};
my $rpmcmd = ['rpm', '-q', '--qf', '%{EPOCH} %{VERSION}
%{RELEASE}\n',
- "$name.$arch"];
+ $name];
my @output;
eval {
@output = $g->command_lines($rpmcmd);
@@ -887,7 +1271,7 @@ sub _newer_installed
my ($name, $epoch, $version, $release, $arch) = $self->_get_nevra($rpm);
- my @installed = $self->_get_installed($name, $arch);
+ my @installed = $self->_get_installed("$name.$arch");
# Search installed rpms matching <name>.<arch>
my $found = 0;
@@ -955,7 +1339,7 @@ sub _get_deppaths
my ($name, undef, undef, undef, $arch) =
$self->_get_nevra($path);
- my @installed = $self->_get_installed($name, $arch);
+ my @installed = $self->_get_installed("$name.$arch");
if (@installed > 0) {
$required{$path} = 1;
@@ -1056,7 +1440,7 @@ sub _rpmvercmp
=item remove_application(name)
-See BACKEND INTERFACE in L<Sys::VirtV2V::GuestOS> for details.
+Uninstall an application.
=cut
@@ -1350,94 +1734,6 @@ sub prepare_bootable
}
}
- # grubby can sometimes fail to correctly update grub.conf when run from
- # libguestfs. If it looks like this happened, install a new grub config
- # here.
- if (!$found) {
- # Check that an appropriately named kernel and initrd exist
- if ($g->exists("/boot/vmlinuz-$version") &&
- $g->exists("/boot/initrd-$version.img"))
- {
- $initrd = "$prefix/initrd-$version.img";
-
- my $title;
- # No point in dying if /etc/redhat-release can't be read
- eval {
- ($title) = $g->read_lines('/etc/redhat-release');
- };
- $title ||= 'Linux';
-
- # This is how new-kernel-pkg does it
- $title =~ s/ release.*//;
- $title .= " ($version)";
-
- my $default;
- eval {
- $default =
$g->aug_get('/files/boot/grub/menu.lst/default');
- };
-
- if (defined($default)) {
- $g->aug_defvar('template',
- '/files/boot/grub/menu.lst/title['.($default +
1).']');
- }
-
- # If there's no default, take the first entry with a kernel
- else {
- my ($match) =
-
$g->aug_match('/files/boot/grub/menu.lst/title/kernel');
-
- die("No template kernel found in grub")
- unless(defined($match));
-
- $match =~ s/\/kernel$//;
- $g->aug_defvar('template', $match);
- }
-
- # Add a new title node at the end
- $g->aug_defnode('new',
- '/files/boot/grub/menu.lst/title[last()+1]',
- $title);
-
- # N.B. Don't change the order of root, kernel and initrd below,
- # or the guest will not boot.
-
- # Copy root from the template
- $g->aug_set('$new/root',
$g->aug_get('$template/root'));
-
- # Set kernel and initrd to the new values
- $g->aug_set('$new/kernel',
"$prefix/vmlinuz-$version");
- $g->aug_set('$new/initrd',
"$prefix/initrd-$version.img");
-
- # Copy all kernel command-line arguments
- foreach my $arg ($g->aug_match('$template/kernel/*')) {
- # kernel arguments don't necessarily have values
- my $val;
- eval {
- $val = $g->aug_get($arg);
- };
-
- $arg =~ /([^\/]*)$/;
- $arg = $1;
-
- if (defined($val)) {
- $g->aug_set('$new/kernel/'.$arg, $val);
- } else {
- $g->aug_clear('$new/kernel/'.$arg);
- }
- }
-
- my ($new) = $g->aug_match('$new');
- $new =~ /\[(\d+)\]$/;
-
- $g->aug_set('/files/boot/grub/menu.lst/default',
- defined($1) ? $1 - 1 : 0);
- }
-
- else {
- die("Didn't find a grub entry for kernel version
$version");
- }
- }
-
$g->aug_save();
};
diff --git a/v2v/virt-v2v.conf b/v2v/virt-v2v.conf
index 3d33918..fa2293e 100644
--- a/v2v/virt-v2v.conf
+++ b/v2v/virt-v2v.conf
@@ -1,6 +1,66 @@
<virt-v2v>
- <path-root>/var/lib/virt-v2v/software</path-root>
- <iso-path>/var/lib/virt-v2v/transfer.iso</iso-path>
+ <!-- Networks -->
+ <!-- Mappings for the defaults in Xen, ESX and libvirt/KVM
+ to the default in libvirt/KVM -->
+ <!--
+ <network type='bridge' name='xenbr1'>
+ <network type='network' name='default'/>
+ </network>
+
+ <network type='bridge' name='VM Network'>
+ <network type='network' name='default'/>
+ </network>
+
+ <network type='network' name='default'>
+ <network type='network' name='default'/>
+ </network>
+ -->
+
+ <!-- If importing to RHEV, you may want to use the default network name
+ 'rhevm' instead -->
+ <!--
+ <network type='bridge' name='xenbr1'>
+ <network type='network' name='rhevm'/>
+ </network>
+
+ <network type='bridge' name='VM Network'>
+ <network type='network' name='rhevm'/>
+ </network>
+
+ <network type='network' name='default'>
+ <network type='network' name='rhevm'/>
+ </network>
+ -->
+
+ <!--
+ Capabilities
+
+ You shouldn't need to modify these.
+ -->
+ <capability os='linux' distro='rhel' major='5'
name='virtio'>
+ <dep name='kernel' minversion='2.6.18-128.el5'/>
+ <dep name='lvm2' minversion='2.02.40-6.el5'/>
+ </capability>
+
+ <capability os='linux' distro='rhel' major='4'
name='virtio'>
+ <dep name='kernel' minversion='2.6.9-89.EL'/>
+ </capability>
+
+ <!--
+ Local applications
+
+ The applications below are required for updating software in a guest which
+ it is not possible to obtain via the network. Note that the software itself
+ is not provided with virt-v2v. virt-v2v will give an error if any of the
+ software listed below is required but not available. In this case, you
+ should obtain the software and copy it locally to the correct location.
+
+ The default set of packages listed below are the oldest packages which
+ supported VirtIO for each OS. They also have a relatively minimal dependency
+ set, which makes them simpler to install during conversion. If you rely on
+ these packages rather than online update, you MUST apply all relevant
+ security patches immediately after conversion.
+ -->
<!-- RHEL 5
All of these RPMS are from RHEL 5.3, which was the first version of RHEL
@@ -8,20 +68,15 @@
<app os='linux' distro='rhel' major='5' arch='i686'
name='kernel'>
<path>rhel/5/kernel-2.6.18-128.el5.i686.rpm</path>
<dep>ecryptfs-utils</dep>
- <dep>lvm2</dep>
</app>
<app os='linux' distro='rhel' major='5' arch='i686'
name='kernel-PAE'>
<path>rhel/5/kernel-PAE-2.6.18-128.el5.i686.rpm</path>
<dep>ecryptfs-utils</dep>
- <dep>lvm2</dep>
</app>
<app os='linux' distro='rhel' major='5'
arch='x86_64' name='kernel'>
<path>rhel/5/kernel-2.6.18-128.el5.x86_64.rpm</path>
<dep>ecryptfs-utils</dep>
- <dep>lvm2</dep>
</app>
-
- <!-- RHEL 5 Kernel dependencies -->
<app os='linux' distro='rhel' major='5'
arch='x86_64' name='ecryptfs-utils'>
<path>rhel/5/ecryptfs-utils-56-8.el5.x86_64.rpm</path>
</app>
@@ -107,36 +162,7 @@
<path>windows/rhev-apt.exe</path>
</app>
- <!-- Networks -->
- <!-- Mappings for the defaults in Xen, ESX and libvirt/KVM
- to the default in libvirt/KVM -->
- <!--
- <network type='bridge' name='xenbr1'>
- <network type='network' name='default'/>
- </network>
-
- <network type='bridge' name='VM Network'>
- <network type='network' name='default'/>
- </network>
-
- <network type='network' name='default'>
- <network type='network' name='default'/>
- </network>
- -->
-
- <!-- If importing to RHEV, you may want to use the default network name
- 'rhevm' instead -->
- <!--
- <network type='bridge' name='xenbr1'>
- <network type='network' name='rhevm'/>
- </network>
-
- <network type='bridge' name='VM Network'>
- <network type='network' name='rhevm'/>
- </network>
-
- <network type='network' name='default'>
- <network type='network' name='rhevm'/>
- </network>
- -->
+ <!-- Default file locations -->
+ <path-root>/var/lib/virt-v2v/software</path-root>
+ <iso-path>/var/lib/virt-v2v/transfer.iso</iso-path>
</virt-v2v>
diff --git a/v2v/virt-v2v.conf.pod b/v2v/virt-v2v.conf.pod
index b9bd893..61aea5d 100644
--- a/v2v/virt-v2v.conf.pod
+++ b/v2v/virt-v2v.conf.pod
@@ -68,9 +68,102 @@ virt-v2v may have to install software in a guest during the conversion
process
to ensure it boots. An example is replacing a Xen paravirtualised kernel with a
normal kernel. This software will be specific to the guest operating system.
-Software to be installed is specified in the E<lt>appE<gt> element, which is
a
+=head3 Capabilities
+
+A capability describes the set of software required for a specific goal, for
+example VirtIO support. A capability describes only direct dependencies.
+Transitive dependencies will be resolved by the installation method, for example
+yum or L</"Local Installation">.
+
+E<lt>capabilityE<gt> is a child of the root element. There can be any number
of
+E<lt>capabilityE<gt> elements. See L</Searching> for a description of
the
+attributes of E<lt>capabilityE<gt> and how they are matched.
+
+Dependencies are specified in the E<lt>depE<gt> element, which has the
following
+attributes:
+
+=over
+
+=item name
+
+The symbolic name of a dependency. On an rpm-based system this will be the
+package name. This attribute is required.
+
+=item minversion
+
+The minimum required version of the software. For rpm-based systems this must be
+specified as [epoch:]version[-release]. This attribute is required.
+
+=item ifinstalled
+
+A dependency must normally be installed if it is not present, or upgraded if it
+present but too old. If I<ifinstalled> is 'yes', the dependency will be
upgraded
+if is present but too old, but not installed if it is not already present.
+
+=back
+
+=head3 Local Installation
+
+If it is not possible to install required software using the guest's update
+agent, the software can be installed from the conversion host. In this case, it
+must be specified in the E<lt>appE<gt> element. E<lt>appE<gt> is
a
child of the root element. The configuration can specify any number of
-E<lt>appE<gt> elements. E<lt>appE<gt> can have these attributes:
+E<lt>appE<gt> elements. See L</Searching> for a description of the
attribute of
+E<lt>appE<gt> and how they are matched.
+
+The E<lt>appE<gt> element must contain a E<lt>pathE<gt> element,
which specifies
+the path to the software. It may also contain any number of E<lt>depE<gt>
+elements, which specify the names of additional applications which may need to
+be installed. Each dependency will be resolved in the same way as its parent, by
+looking for a match based on os, distro, major, minor and arch.
+
+virt-v2v will attempt to install dependencies first. A dependency will only be
+installed if it is not already installed, or the installed version is older than
+the specified version. On x86_64, virt-v2v will additionally check if an i386
+version need to by updated, but only if any i386 version of the package is
+already installed.
+
+Paths given in E<lt>pathE<gt> must be absolute, unless there is a top level
+E<lt>path-rootE<gt> element. If it exists, all E<lt>pathE<gt>
elements will be
+relative to E<lt>path-rootE<gt>.
+
+virt-v2v passes software to the guest by creating an iso image and passing it to
+the guest as a cd-rom drive. The path to this iso image must be specified in a
+top level E<lt>iso-pathE<gt> element.
+
+The following example specifies the location of 'kernel' for RHEL 5, all minor
+versions, on i686:
+
+ <app os='linux' distro='rhel' major='5' arch='i686'
name='kernel'>
+ <path>rhel/5/kernel-2.6.18-128.el5.i686.rpm</path>
+ <dep>ecryptfs-utils</dep>
+ <dep>lvm2</dep>
+ </app>
+ <app os='linux' distro='rhel' major='5' arch='i386'
name='ecryptfs-utils'>
+ <path>rhel/5/ecryptfs-utils-56-8.el5.i386.rpm</path>
+ </app>
+ <app os='linux' distro='rhel' major='5' arch='i386'
name='lvm2'>
+ <path>rhel/5/lvm2-2.02.40-6.el5.i386.rpm</path>
+ <dep>device-mapper</dep>
+ <dep>device-mapper-event</dep>
+ </app>
+
+ <path-root>/var/lib/virt-v2v/software</path-root>
+ <iso-path>/var/lib/virt-v2v/transfer.iso</iso-path>
+
+The kernel can be found at
+/var/lib/virt-v2v/software/rhel/5/kernel-2.6.18-128.el5.i686.rpm. It has 2
+direct dependencies: ecryptfs and lvm2. ecryptfs-utils has no additional
+dependencies, but lvm2 has 2 further dependencies (not shown for brevity). All
+dependencies will also be installed if they are not present, or are too old. All
+dependency paths are also relative to /var/lib/virt-v2v/software. virt-v2v will
+create a transfer iso image containing all paths and dependencies at
+/var/lib/virt-v2v/transfer.iso.
+
+=head3 Searching
+
+Both E<lt>capabilityE<gt> and E<lt>appE<gt> are matched in the
same way, based
+on the following attributes:
=over
@@ -105,11 +198,11 @@ The guest architecture, as returned by virt-inspector.
=back
-virt-v2v requests a file from the configuration by its symbolic name, searching
-based on its additional attributes. If an attribute is missing from the
-E<lt>appE<gt> element, it will match any value. If multiple
E<lt>appE<gt>
-elements would match a given search, virt-v2v will choose the most specific
-match. Specifically, it searches in the following order:
+virt-v2v searches for an E<lt>appE<gt> or E<lt>capabilityE<gt> by
symbolic name,
+matching based on its additional attributes. If an attribute is missing it will
+match any value. If multiple elements would match a given search, virt-v2v will
+choose the most specific match. Specifically, it searches in the following
+order:
=over
@@ -139,57 +232,8 @@ os
=back
-If virt-v2v doesn't find a matching E<lt>appE<gt>, it will quit with an
error
-describing what it was looking for.
-
-The E<lt>appE<gt> element must contain a E<lt>pathE<gt> element,
which specifies
-the path to the software. It may also contain any number of E<lt>depE<gt>
-elements, which specify the names of additional applications which may need to
-be installed. Each dependency will be resolved in the same way as its parent, by
-looking for a match based on os, major, minor and arch.
-
-virt-v2v will attempt to install dependencies first. A dependency will only be
-installed if it is not already installed, or the installed version is older than
-the specified version. On x86_64, virt-v2v will additionally check if an i386
-version need to by updated, but only if any i386 version of the package is
-already installed.
-
-Paths given in E<lt>pathE<gt> must be absolute, unless there is a top level
-E<lt>path-rootE<gt> element. If it exists, all E<lt>pathE<gt>
elements will be
-relative to E<lt>path-rootE<gt>.
-
-virt-v2v passes software to the guest by creating an iso image and passing it to
-the guest as a cd-rom drive. The path to this iso image must be specified in a
-top level E<lt>iso-pathE<gt> element.
-
-The following example specifies the location of 'kernel' for RHEL 5, all minor
-versions, on i686:
-
- <path-root>/var/lib/virt-v2v/software</path-root>
- <iso-path>/var/lib/virt-v2v/transfer.iso</iso-path>
-
- <app os='linux' distro='rhel' major='5' arch='i686'
name='kernel'>
- <path>rhel/5/kernel-2.6.18-128.el5.i686.rpm</path>
- <dep>ecryptfs-utils</dep>
- <dep>lvm2</dep>
- </app>
- <app os='linux' distro='rhel' major='5' arch='i386'
name='ecryptfs-utils'>
- <path>rhel/5/ecryptfs-utils-56-8.el5.i386.rpm</path>
- </app>
- <app os='linux' distro='rhel' major='5' arch='i386'
name='lvm2'>
- <path>rhel/5/lvm2-2.02.40-6.el5.i386.rpm</path>
- <dep>device-mapper</dep>
- <dep>device-mapper-event</dep>
- </app>
-
-The kernel can be found at
-/var/lib/virt-v2v/software/rhel/5/kernel-2.6.18-128.el5.i686.rpm. It has 2
-direct dependencies: ecryptfs and lvm2. ecryptfs-utils has no additional
-dependencies, but lvm2 has 2 further dependencies (not shown for brevity). All
-dependencies will also be installed if they are not present, or are too old. All
-dependency paths are also relative to /var/lib/virt-v2v/software. virt-v2v will
-create a transfer iso image containing all paths and dependencies at
-/var/lib/virt-v2v/transfer.iso.
+If virt-v2v doesn't find a match it will quit with an error describing what it
+was looking for.
=head1 COPYRIGHT
diff --git a/v2v/virt-v2v.pl b/v2v/virt-v2v.pl
index 8395d93..685ade8 100755
--- a/v2v/virt-v2v.pl
+++ b/v2v/virt-v2v.pl
@@ -547,30 +547,16 @@ To perform the conversion, run:
where C<< <domain>.xml >> is the path to the exported guest
domain's xml, and
C<< <pool> >> is the local storage pool where copies of the guest's
disks will
-be created. virt-v2v.conf should specify:
+be created. See L<virt-v2v.conf(5)> for a details of virt-v2v.conf.
-=over
-
-=item *
-
-a mapping for the guest's network configuration, unless a default was specified
-on the command line with I<--bridge> or I<--network>.
-
-=item *
-
-app definitions for any required replacement kernels.
-
-=back
-
-See L<virt-v2v.conf(5)> for details.
-
-It is possible to avoid specifying replacement kernels in the virt-v2v config
-file by ensuring that the guest has an appropriate kernel installed prior to
-conversion. If your guest uses a Xen paravirtualised kernel (it would be called
-something like kernel-xen or kernel-xenU), you can install a regular kernel,
-which won't reference a hypervisor in its name, alongside it. You shouldn't make
-this newly installed kernel your default kernel because Xen may not boot it.
-virt-v2v will make it the default during conversion.
+If it is not possible to provide software updates over the network in your
+environment, it is still possible to avoid specifying replacement kernels in the
+virt-v2v config file by ensuring that the guest has an appropriate kernel
+installed prior to conversion. If your guest uses a Xen paravirtualised kernel
+(it would be called something like kernel-xen or kernel-xenU), you can install a
+regular kernel, which won't reference a hypervisor in its name, alongside it.
+You shouldn't make this newly installed kernel your default kernel because Xen
+may not boot it. virt-v2v will make it the default during conversion.
=head2 CONVERTING A GUEST FROM VMWARE ESX
@@ -611,9 +597,7 @@ converted.
=back
-virt-v2v.conf should specify a mapping for the guest's network configuration,
-unless a default was specified on the command line with I<--bridge> or
-I<--network>. See L<virt-v2v.conf(5)> for details.
+See L<virt-v2v.conf(5)> for a details of virt-v2v.conf.
=head3 Authenticating to the ESX server
@@ -677,9 +661,7 @@ virt-v2v -f virt-v2v.conf -o rhev -osd <export_sd>
<domain>
=back
-Ensure that I<virt-v2v.conf> contains a correct network mapping for your target
-RHEV configuration, or that you have specified a default mapping on the command
-line with either I<--bridge> or I<--network>.
+See L<virt-v2v.conf(5)> for details of virt-v2v.conf.
=head1 RUNNING THE CONVERTED GUEST
@@ -806,6 +788,7 @@ Describe the bug accurately, and give a way to reproduce it.
=head1 SEE ALSO
+L<virt-v2v.conf(5)>,
L<virt-manager(1)>,
L<http://libguestfs.org/>.
--
1.6.6.1