This removes another chunk of functionality from GuestOS.
---
MANIFEST | 1 +
lib/Sys/VirtV2V/Config.pm | 339 +++++++++++++++++++++++++++++++++++++
lib/Sys/VirtV2V/Converter.pm | 56 +-----
lib/Sys/VirtV2V/GuestOS.pm | 94 ----------
lib/Sys/VirtV2V/GuestOS/RedHat.pm | 46 ++++--
v2v/virt-v2v.pl | 96 +----------
6 files changed, 385 insertions(+), 247 deletions(-)
create mode 100644 lib/Sys/VirtV2V/Config.pm
diff --git a/MANIFEST b/MANIFEST
index a83d682..65b5a8e 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -6,6 +6,7 @@ lib/Sys/VirtV2V.pm
lib/Sys/VirtV2V/ExecHelper.pm
lib/Sys/VirtV2V/GuestOS.pm
lib/Sys/VirtV2V/GuestOS/RedHat.pm
+lib/Sys/VirtV2V/Config.pm
lib/Sys/VirtV2V/Converter.pm
lib/Sys/VirtV2V/Converter/Linux.pm
lib/Sys/VirtV2V/Connection.pm
diff --git a/lib/Sys/VirtV2V/Config.pm b/lib/Sys/VirtV2V/Config.pm
new file mode 100644
index 0000000..b9e4d37
--- /dev/null
+++ b/lib/Sys/VirtV2V/Config.pm
@@ -0,0 +1,339 @@
+# Sys::VirtV2V::Config
+# Copyright (C) 2009 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+package Sys::VirtV2V::Config;
+
+use strict;
+use warnings;
+
+use File::Spec;
+use File::stat;
+use XML::DOM;
+use XML::DOM::XPath;
+
+use Sys::VirtV2V::ExecHelper;
+use Sys::VirtV2V::UserMessage qw(user_message);
+
+use Locale::TextDomain 'virt-v2v';
+
+=pod
+
+=head1 NAME
+
+Sys::VirtV2V::Config - Manage virt-v2v's configuration file
+
+=head1 SYNOPSIS
+
+ use Sys::VirtV2V::Config;
+
+ $eh = Sys::VirtV2V::Config->new($config_path);
+
+ my $isopath = $config->get_transfer_iso();
+ my ($path, $deps) = $config->match_app($desc, $name, $arch);
+ my ($name, $type) = $config->map_network($oldname, $oldtype);
+
+=head1 DESCRIPTION
+
+Sys::VirtV2V::Config parses and queries the virt-v2v config file.
+
+=head1 METHODS
+
+=over
+
+=item new(path)
+
+Create a new Sys::VirtV2V::Config object to operate on the config file at
+I<path>.
+
+=cut
+
+sub new
+{
+ my $class = shift;
+ my ($path) = @_;
+
+ my $self = {};
+ bless($self, $class);
+
+ die(user_message(__x("Config file {path} doesn't exist",
+ path => $path))) unless (-e $path);
+
+ die(user_message(__x("Don't have permissions to read {path}",
+ path => $path))) unless (-r $path);
+
+ eval {
+ $self->{dom} = new XML::DOM::Parser->parsefile($path);
+ };
+
+ die(user_message(__x("Unable to parse config file {path}: {error}",
+ path => $path, error => $@))) if ($@);
+
+ $self->{path} = $path;
+ return $self;
+}
+
+=item get_transfer_iso
+
+Return the path to an iso image containing all software defined in the config
+file. Returns undef if no transfer iso is required.
+
+=cut
+
+sub get_transfer_iso
+{
+ my $self = shift;
+
+ my $dom = $self->{dom};
+
+ # path-root doesn't have to be defined
+ my ($root) = $dom->findnodes('/virt-v2v/path-root/text()');
+ $root = $root->getData() if (defined($root));
+
+ # Construct a list of path arguments to mkisofs from paths referenced in the
+ # config file
+ # We use a hash here to avoid duplicates
+ my %path_args;
+ foreach my $path ($dom->findnodes('/virt-v2v/app/path/text() | '.
+ '/virt-v2v/app/dep/text()')) {
+ $path = $path->getData();
+
+ # Get the absolute path if iso-root was defined
+ my $abs;
+ if (defined($root)) {
+ $abs = File::Spec->catfile($root, $path);
+ } else {
+ $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;
+ }
+
+ # Nothing further to do if there are no paths
+ return if (keys(%path_args) == 0);
+
+ # Get the path of the transfer iso
+ my ($iso_path) = $dom->findnodes('/virt-v2v/iso-path/text()');
+
+ # We need this
+ die(user_message(__"<iso-path> must be specified in the configuration
".
+ "file")) unless (defined($iso_path));
+ $iso_path = $iso_path->getData();
+
+ # 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}",
+ path => $iso_path, error => $!)));
+
+ my $config_st = stat($self->{path})
+ or die(user_message(__x("Unable to stat config file {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);
+ }
+
+ # Re-create the transfer iso
+ my $eh = Sys::VirtV2V::ExecHelper->run
+ ('mkisofs', '-o', $iso_path,
+ '-r', '-J',
+ '-V', '__virt-v2v_transfer__',
+ '-graft-points', keys(%path_args));
+ die(user_message(__x("Failed to create transfer iso. ".
+ "Command output was:\n{output}",
+ output => $eh->output()))) unless ($eh->status() ==
0);
+
+ 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
+{
+ my ($desc, $name, $arch) = @_;
+
+ my $distro = $desc->{distro};
+ my $major = $desc->{major_version};
+ my $minor = $desc->{minor_version};
+
+ my $search = "distro='$distro' name='$name'";
+ $search .= " major='$major'" if (defined($major));
+ $search .= " minor='$minor'" if (defined($minor));
+ $search .= " arch='$arch'";
+
+ return $search;
+}
+
+=item match_app
+
+Return a matching app entry from the virt-v2v configuration. The entry is
+returned as a list containing 2 values. The first contains the path to the
+application itself. The second contains an arrayref containing the paths of all
+the app's listed dependencies.
+
+=cut
+
+sub match_app
+{
+ my $self = shift;
+
+ my ($desc, $name, $arch) = @_;
+
+ my $dom = $self->{dom};
+
+ my $distro = $desc->{distro};
+ my $major = $desc->{major_version};
+ my $minor = $desc->{minor_version};
+
+ # Check we've got at least a distro from OS detection
+ die(user_message(__"Didn't detect OS distribution"))
+ unless (defined($distro));
+
+ # Create a list of xpath queries against the config which look for a
+ # matching <app> config entry in descending order of specificity
+ my @queries;
+ if (defined($major)) {
+ if (defined($minor)) {
+ push(@queries, _app_query($name, $distro, $major, $minor, $arch));
+ push(@queries, _app_query($name, $distro, $major, $minor, undef));
+ }
+
+ push(@queries, _app_query($name, $distro, $major, undef, $arch));
+ push(@queries, _app_query($name, $distro, $major, undef, undef));
+ }
+
+ push(@queries, _app_query($name, $distro, undef, undef, $arch));
+ push(@queries, _app_query($name, $distro, undef, undef, undef));
+
+ # Use the results of the first query which returns a result
+ my $app;
+ foreach my $query (@queries) {
+ ($app) = $dom->findnodes($query);
+ last if (defined($app));
+ }
+
+ die(user_message(__x("No app in config matches {search}",
+ search => get_app_search($desc, $name, $arch))))
+ unless (defined($app));
+
+ my %app;
+ my ($path) = $app->findnodes('path/text()');
+ die(user_message(__x("app entry in config doesn't contain a path:
{xml}",
+ xml => $app->toString()))) unless (defined($path));
+ $path = $path->getData();
+
+ my @deps;
+ foreach my $dep ($app->findnodes('dep/text()')) {
+ push(@deps, $dep->getData());
+ }
+
+ return ($path, \@deps);
+}
+
+sub _app_query
+{
+ my ($name, $distro, $major, $minor, $arch) = @_;
+
+ my $query = "/virt-v2v/app[\@name='$name' and \@os='$distro' and
";
+ $query .= defined($major) ? "\@major='$major'" :
'not(@major)';
+ $query .= ' and ';
+ $query .= defined($minor) ? "\@minor='$minor'" :
'not(@minor)';
+ $query .= ' and ';
+ $query .= defined($arch) ? "\@arch='$arch'" :
'not(@arch)';
+ $query .= ']';
+
+ return $query;
+}
+
+=item map_network(oldname, oldtype)
+
+Return a new network name/type for I<oldname> and I<oldtype> from the
config.
+Returns a list of 2 values: (I<name>, I<type>)
+
+=cut
+
+sub map_network
+{
+ my $self = shift;
+ my ($oldname, $oldtype) = @_;
+
+ my ($mapping) = $self->{dom}->findnodes
+ ("/virt-v2v/network[\@type='$oldtype' and
\@name='$oldname']".
+ "/network");
+
+ unless (defined($mapping)) {
+ print STDERR user_message(__x("No mapping found for '{type}'
".
+ "interface: {name}",
+ type => $oldtype,
+ name => $oldname));
+ return;
+ }
+
+ my $newtype = $mapping->getAttributeNode('type');
+ $newtype &&= $newtype->getValue();
+ my $newname = $mapping->getAttributeNode('name');
+ $newname &&= $newname->getValue();
+
+ # Check type and name are defined for the mapping
+ unless (defined($newtype) && defined($newname)) {
+ print STDERR user_message(__x("WARNING: Invalid network ".
+ "mapping in config: {config}",
+ config => $mapping->toString()));
+ return;
+ }
+
+ # Check type is something we recognise
+ unless ($newtype eq 'network' || $newtype eq 'bridge') {
+ print STDERR user_message(__x("WARNING: Unknown interface type ".
+ "{type} in network mapping: {config}",
+ type => $newtype,
+ config => $mapping->toString()));
+ }
+
+ return ($newname, $newtype);
+}
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright (C) 2010 Red Hat Inc.
+
+=head1 LICENSE
+
+Please see the file COPYING.LIB for the full license.
+
+=head1 SEE ALSO
+
+L<virt-v2v(1)>,
+L<http://libguestfs.org/>.
+
+=cut
+
+1;
diff --git a/lib/Sys/VirtV2V/Converter.pm b/lib/Sys/VirtV2V/Converter.pm
index 5dc8550..08f1e8f 100644
--- a/lib/Sys/VirtV2V/Converter.pm
+++ b/lib/Sys/VirtV2V/Converter.pm
@@ -442,57 +442,19 @@ sub _map_networks
exit(1);
}
- _update_interface($if, $name, $type, $config);
- }
-}
+ my ($newname, $newtype) = $config->map_network($name->getValue(),
+ $type);
-sub _update_interface
-{
- my ($if, $oldname, $oldtype, $config) = @_;
-
- my $oldnameval = $oldname->getValue();
- my ($mapping) = $config->findnodes
- ("/virt-v2v/network[\@type='$oldtype' and
\@name='$oldnameval']".
- "/network");
-
- unless (defined($mapping)) {
- print STDERR user_message(__x("No mapping found for '{type}'
".
- "interface: {name}",
- type => $oldtype,
- name => $oldnameval));
- return;
- }
+ my ($source) = $if->findnodes('source');
- my $newtype = $mapping->getAttributeNode('type');
- $newtype &&= $newtype->getValue();
- my $newname = $mapping->getAttributeNode('name');
- $newname &&= $newname->getValue();
-
- # Check type and name are defined for the mapping
- unless (defined($newtype) && defined($newname)) {
- print STDERR user_message(__x("WARNING: Invalid network ".
- "mapping in config: {config}",
- config => $mapping->toString()));
- return;
- }
+ # Replace @bridge or @network in the source element with the correct
+ # mapped attribute name and value
+ $source->removeAttributeNode($name);
+ $source->setAttribute($newtype, $newname);
- # Check type is something we recognise
- unless ($newtype eq 'network' || $newtype eq 'bridge') {
- print STDERR user_message(__x("WARNING: Unknown interface type ".
- "{type} in network mapping: {config}",
- type => $newtype,
- config => $mapping->toString()));
+ # Update the type of the interface
+ $if->setAttribute('type', $newtype);
}
-
- my ($source) = $if->findnodes('source');
-
- # Replace @bridge or @network in the source element with the correct mapped
- # attribute name and value
- $source->removeAttributeNode($oldname);
- $source->setAttribute($newtype, $newname);
-
- # Update the type of the interface
- $if->setAttribute('type', $newtype);
}
=back
diff --git a/lib/Sys/VirtV2V/GuestOS.pm b/lib/Sys/VirtV2V/GuestOS.pm
index 3fb59ce..6165edd 100644
--- a/lib/Sys/VirtV2V/GuestOS.pm
+++ b/lib/Sys/VirtV2V/GuestOS.pm
@@ -150,100 +150,6 @@ sub get_memory_kb
return $mem_kb->getData();
}
-=item match_app
-
-Return a matching app entry from the virt-v2v configuration. The entry is
-returned as a hashref containing 2 entries. I<path> contains the path to the
-application itself. I<deps> contains an arrayref containing the paths of all the
-app's listed dependencies.
-
-=cut
-
-sub match_app
-{
- my $self = shift;
-
- my ($name, $arch) = @_;
-
- my $config = $self->{config};
-
- my $desc = $self->{desc};
- my $distro = $desc->{distro};
- my $major = $desc->{major_version};
- my $minor = $desc->{minor_version};
-
- # Check we've got at least a distro from OS detection
- die(user_message(__"Didn't detect OS distribution"))
- unless (defined($distro));
-
- my $search = "distro='$distro' name='$name'";
- $search .= " major='$major'" if (defined($major));
- $search .= " minor='$minor'" if (defined($minor));
- $search .= " arch='$arch'";
-
- die(user_message(__x("No config specified. No app match for {search}",
- search => $search))) unless (defined($config));
-
- # Create a list of xpath queries against the config which look for a
- # matching <app> config entry in descending order of specificity
- my @queries;
- if (defined($major)) {
- if (defined($minor)) {
- push(@queries, _app_query($name, $distro, $major, $minor, $arch));
- push(@queries, _app_query($name, $distro, $major, $minor, undef));
- }
-
- push(@queries, _app_query($name, $distro, $major, undef, $arch));
- push(@queries, _app_query($name, $distro, $major, undef, undef));
- }
-
- push(@queries, _app_query($name, $distro, undef, undef, $arch));
- push(@queries, _app_query($name, $distro, undef, undef, undef));
-
- # Use the results of the first query which returns a result
- my $app;
- foreach my $query (@queries) {
- ($app) = $config->findnodes($query);
- last if (defined($app));
- }
-
- die(user_message(__x("No app in config matches {search}",
- search => $search))) unless (defined($app));
-
- my %app;
- my ($path) = $app->findnodes('path/text()');
- die(user_message(__x("app entry in config doesn't contain a path:
{xml}",
- xml => $app->toString()))) unless (defined($path));
- $path = $path->getData();
-
- my @deps;
- foreach my $dep ($app->findnodes('dep/text()')) {
- push(@deps, $dep->getData());
- }
-
- # Return a hash containing the application path and its dependencies
- my %ret;
- $ret{path} = $path;
- $ret{deps} = \@deps;
-
- return \%ret;
-}
-
-sub _app_query
-{
- my ($name, $distro, $major, $minor, $arch) = @_;
-
- my $query = "/virt-v2v/app[\@name='$name' and \@os='$distro' and
";
- $query .= defined($major) ? "\@major='$major'" :
'not(@major)';
- $query .= ' and ';
- $query .= defined($minor) ? "\@minor='$minor'" :
'not(@minor)';
- $query .= ' and ';
- $query .= defined($arch) ? "\@arch='$arch'" :
'not(@arch)';
- $query .= ']';
-
- return $query;
-}
-
=back
=head1 BACKEND INTERFACE
diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
index d062da1..f945847 100644
--- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
+++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
@@ -475,9 +475,20 @@ sub add_kernel
}
}
- my $app;
+ my ($app, $deps);
eval {
- $app = $self->match_app($kernel_pkg, $kernel_arch);
+ 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, $deps) = $config->match_app($desc, $kernel_pkg, $kernel_arch);
};
# Return undef if we didn't find a kernel
if ($@) {
@@ -485,13 +496,11 @@ sub add_kernel
return undef;
}
- my $path = $app->{path};
-
- return undef if($self->_is_installed($path));
+ return undef if($self->_is_installed($app));
my @install;
# Install any kernel dependencies which aren't already installed
- foreach my $dep (@{$app->{deps}}) {
+ foreach my $dep (@$deps) {
push(@install, $dep) unless($self->_is_installed($dep));
}
$self->_install_rpms(1, @install);
@@ -500,7 +509,7 @@ sub add_kernel
my $version;
my $g = $self->{g};
foreach my $file ($g->command_lines
- (["rpm", "-qlp", $self->_transfer_path($path)]))
+ (["rpm", "-qlp", $self->_transfer_path($app)]))
{
if($file =~ m{^/boot/vmlinuz-(.*)$}) {
$version = $1;
@@ -509,9 +518,9 @@ sub add_kernel
}
die(user_message(__x("{path} doesn't contain a valid kernel",
- path => $path))) if(!defined($version));
+ path => $app))) if(!defined($version));
- $self->_install_rpms(0, ($path));
+ $self->_install_rpms(0, ($app));
# Make augeas reload so it'll find the new kernel
$g->aug_load();
@@ -611,17 +620,26 @@ sub add_application
my $self = shift;
my $label = shift;
- my $user_arch = $self->{desc}->{arch};
+ my $desc = $self->{desc};
+ 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 = $self->match_app($label, $user_arch);
+ my ($app, $deps) = $config->match_app($self->{desc}, $label, $user_arch);
# Nothing to do if it's already installed
- return if($self->_is_installed($app->{path}));
+ return if($self->_is_installed($app));
- my @install = ($app->{path});
+ my @install = ($app);
# Add any dependencies which aren't already installed to the install set
- foreach my $dep (@{$app->{deps}}) {
+ foreach my $dep (@$deps) {
push(@install, $dep) unless ($self->_is_installed($dep));
}
diff --git a/v2v/virt-v2v.pl b/v2v/virt-v2v.pl
index c7ebad3..66b1844 100755
--- a/v2v/virt-v2v.pl
+++ b/v2v/virt-v2v.pl
@@ -21,8 +21,6 @@ use strict;
use Pod::Usage;
use Getopt::Long;
-use File::Spec;
-use File::stat;
use Locale::TextDomain 'virt-v2v';
@@ -32,6 +30,7 @@ use Sys::Guestfs::Lib qw(open_guest get_partitions
inspect_all_partitions
inspect_in_detail);
use Sys::VirtV2V;
+use Sys::VirtV2V::Config;
use Sys::VirtV2V::Converter;
use Sys::VirtV2V::Connection::LibVirt;
use Sys::VirtV2V::Connection::LibVirtXML;
@@ -215,21 +214,7 @@ GetOptions ("help|?" => sub {
# Read the config file if one was given
my $config;
-if(defined($config_file)) {
- # Check we can access the config file
- die(user_message(__x("Config file {path} doesn't exist",
- path => $config_file))) unless (-e $config_file);
-
- die(user_message(__x("Don't have permissions to read {path}",
- path => $config_file))) unless (-r $config_file);
-
- eval {
- $config = new XML::DOM::Parser->parsefile($config_file);
- };
-
- die(user_message(__x("Unable to parse config file {path}: {error}",
- path => $config_file, error => $@))) if ($@);
-}
+$config = Sys::VirtV2V::Config->new($config_file) if defined($config_file);
my $target;
if ($output_method eq "libvirt") {
@@ -312,7 +297,8 @@ exit(1) unless(defined($dom));
my $storage = $conn->get_storage_paths();
# Create the transfer iso if required
-my $transferiso = get_transfer_iso($config, $config_file);
+my $transferiso;
+$transferiso = $config->get_transfer_iso() if (defined($config));
if ($output_method eq 'rhev') {
$) = "36 36";
@@ -380,80 +366,6 @@ sub close_guest_handle
}
}
-sub get_transfer_iso
-{
- my ($config, $config_file) = @_;
-
- # Nothing to do if there's no config
- return undef unless (defined($config));
-
- # path-root doesn't have to be defined
- my ($root) = $config->findnodes('/virt-v2v/path-root/text()');
- $root = $root->getData() if (defined($root));
-
- # Construct a list of path arguments to mkisofs from paths referenced in the
- # config file
- # We actually use a hash here to avoid duplicates
- my %path_args;
- foreach my $path ($config->findnodes('/virt-v2v/app/path/text() | '.
- '/virt-v2v/app/dep/text()')) {
- $path = $path->getData();
-
- # Get the absolute path if iso-root was defined
- my $abs;
- if (defined($root)) {
- $abs = File::Spec->catfile($root, $path);
- } else {
- $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;
- }
-
- # Nothing further to do if there are no paths
- return if (keys(%path_args) == 0);
-
- # Get the path of the transfer iso
- my ($iso_path) = $config->findnodes('/virt-v2v/iso-path/text()');
-
- # We need this
- die(user_message(__"<iso-path> must be specified in the configuration
".
- "file")) unless (defined($iso_path));
- $iso_path = $iso_path->getData();
-
- # Check that 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}",
- path => $iso_path, error => $!)));
-
- my $config_st = stat($config_file)
- or die(user_message(__x("Unable to stat config file {path}: ".
- "{error}",
- path => $config_file, 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);
- }
-
- # Re-create the transfer iso
- my $eh = Sys::VirtV2V::ExecHelper->run
- ('mkisofs', '-o', $iso_path,
- '-r', '-J',
- '-V', '__virt-v2v_transfer__',
- '-graft-points', keys(%path_args));
- die(user_message(__x("Failed to create transfer iso. ".
- "Command output was:\n{output}",
- output => $eh->output()))) unless ($eh->status() ==
0);
-
- return $iso_path;
-}
-
sub get_guestfs_handle
{
my ($storage, $transferiso) = @_;
--
1.6.6.1