1#
2# (c) Jan Gehring <jan.gehring@gmail.com>
3#
4# vim: set ts=2 sw=2 tw=0:
5# vim: set expandtab:
6
7package Rex::Virtualization::LibVirt::import;
8
9use 5.010001;
10use strict;
11use warnings;
12
13our $VERSION = '1.13.4'; # VERSION
14
15use Rex::Logger;
16use Rex::Helper::Run;
17use Rex::Commands::Fs;
18use File::Basename;
19use Rex::Virtualization::LibVirt::create;
20use Data::Dumper;
21
22#
23# %opt = (cpus => 2, memory => 512)
24#
25sub execute {
26  my ( $class, $arg1, %opt ) = @_;
27
28  unless ($arg1) {
29    die("You have to define the vm name!");
30  }
31
32  my $dom = $arg1;
33  Rex::Logger::debug( "importing: $dom -> " . $opt{file} );
34
35  my $cwd = i_run "pwd";
36  chomp $cwd;
37
38  my $dir = dirname $opt{file};
39  my ( undef, undef, $suffix ) = fileparse( $opt{file}, qr{\.[^.]*} );
40  $opt{storage_path} = $cwd . '/storage' unless ( $opt{storage_path} );
41  my $file = $opt{storage_path} . '/' . $dom . $suffix;
42  i_run "mkdir -p $opt{storage_path}";
43
44  my $format = "qcow2";
45
46  my @serial_devices;
47  if ( exists $opt{serial_devices} ) {
48    @serial_devices = @{ $opt{serial_devices} };
49  }
50
51  if ( $opt{file} =~ m/\.ova$/ ) {
52    Rex::Logger::debug("Importing ova file. Try to convert with qemu-img");
53    $file =~ s/\.[a-z]+$//;
54
55    my @vmdk = grep { m/\.vmdk$/ } i_run "tar -C '$dir' -vxf '$opt{file}'";
56
57    Rex::Logger::debug("converting '$cwd/tmp/$vmdk[0]' -> '$file.qcow2'");
58    i_run "qemu-img convert -O qcow2 '$cwd/tmp/$vmdk[0]' '$file.qcow2'",
59      fail_ok => 1;
60
61    if ( $? != 0 ) {
62      Rex::Logger::info(
63        "Can't import and convert $opt{file}. You qemu-img version seems not "
64          . " to support this format.",
65        "warn"
66      );
67      die("Error importing VM $opt{file}");
68    }
69
70    $file = "$file.qcow2";
71  }
72  else {
73    Rex::Logger::debug("Importing kvm compatible file.");
74    Rex::Logger::debug("Copying $opt{file} -> $file");
75    cp $opt{file}, $file;
76    if ( $file =~ m/\.gz$/ ) {
77      Rex::Logger::debug("Extracting gzip'ed file $file");
78      i_run "gunzip -q -f '$file'";
79      $file =~ s/\.gz$//;
80    }
81  }
82
83  my ($format_out) = grep { m/^file format:/ } i_run "qemu-img info '$file'",
84    fail_ok => 1;
85  if ( $format_out =~ m/^file format: (.*)$/i ) {
86    $format = $1;
87  }
88
89  my @network = values %{ $opt{__network} };
90  if ( scalar @network == 0 ) {
91
92    # create default network
93    push @network,
94      {
95      type    => "network",
96      network => "default",
97      };
98  }
99
100  for (@network) {
101    $_->{type} ||= "network";
102    $_->{type} = "bridge"  if ( $_->{type} && $_->{type} eq "bridged" );
103    $_->{type} = "network" if ( $_->{type} eq "nat" );
104    if ( $_->{type} eq "network" && !exists $_->{network} ) {
105      $_->{network} = "default";
106    }
107  }
108
109  Rex::Virtualization::LibVirt::create->execute(
110    $dom,
111    storage => [
112      {
113        file        => "$file",
114        dev         => "vda",
115        driver_type => $format,
116      },
117    ],
118    network        => \@network,
119    serial_devices => \@serial_devices,
120    memory         => $opt{memory},
121    cpus           => $opt{cpus},
122  );
123
124  if ( exists $opt{__forward_port} ) {
125
126    # currently not supported
127    Rex::Logger::info(
128      "Port-forwarding is currently not supported for KVM boxes.", "warn" );
129  }
130
131}
132
1331;
134