File Coverage

backend/vagrant.pm
Criterion Covered Total %
statement 155 155 100.0
total 155 155 100.0


line stmt code
1   # Copyright 2021 SUSE LLC
2   # SPDX-License-Identifier: GPL-2.0-or-later
3    
4    
5   use Mojo::Base 'backend::virt', -signatures;
6 1 use bmwqemu;
  1  
  1  
7 1 use Mojo::File;
  1  
  1  
8 1 use Cwd qw(abs_path);
  1  
  1  
9 1 use File::Temp;
  1  
  1  
10 1 use File::chdir;
  1  
  1  
11 1 use IPC::Run;
  1  
  1  
12 1 use Time::Seconds;
  1  
  1  
13 1  
  1  
  1  
14   my $self = $class->SUPER::new;
15 10 my $vars = \%bmwqemu::vars;
  10  
  10  
16 10  
17 10 $self->{vagrant_cwd} = File::Temp->newdir();
18   $self->{up_timeout} = $vars->{VAGRANT_UP_TIMEOUT} // 300;
19 10 $self->{provider} = $vars->{VAGRANT_PROVIDER} // die 'Need variable \'VAGRANT_PROVIDER\'';
20 10 $self->{box_name} = $vars->{VAGRANT_BOX} // die 'Need variable \'VAGRANT_BOX\'';
21 10 $self->{box_url} = $vars->{VAGRANT_BOX_URL};
22 10  
23 10 if (substr($self->{box_name}, 0, 1) eq '/') {
24   my $asset_dir = $vars->{VAGRANT_ASSETDIR} // die 'Need variable \'VAGRANT_ASSETDIR\' when using local vagrant boxes';
25 10 my $box_abs_path = undef;
26 3  
27 3 opendir(my $dh, $asset_dir) or die "Could not opendir $asset_dir: $!";
28    
29 3 my $box_path = abs_path("$asset_dir$self->{box_name}");
30   die "File $box_path does not exist" unless (-e $box_path);
31 2 $self->{box_name} = $box_path;
32 2 }
33 1  
34   $self->{libvirt_pool_name} = undef;
35    
36 8 my $path = Mojo::File::path($self->{vagrant_cwd})->make_path();
37   $self->{vagrantfile} = $path->child("Vagrantfile");
38 8 bmwqemu::diag("Writing Vagrantfile to $self->{vagrantfile}");
39 8  
40 8 my $vagrant_file_contents = <<END;
41   Vagrant.configure("2") do |config|
42 8 config.vm.box = "$self->{box_name}"
43   END
44   if (defined($self->{box_url})) {
45   $vagrant_file_contents .= <<END;
46 8 config.vm.box_url = "$self->{box_url}"
47 1 END
48   }
49   $vagrant_file_contents .= <<END;
50   config.vm.synced_folder ".", "/vagrant", disabled: true
51 8 END
52    
53    
54   if ($self->{provider} eq 'virtualbox') {
55   $vagrant_file_contents .= <<END;
56 8 config.vm.provider "virtualbox" do |v|
57 3 v.memory = $vars->{QEMURAM}
58   v.cpus = $vars->{QEMUCPUS}
59   end
60   END
61   } elsif ($self->{provider} eq 'libvirt') {
62   $self->{libvirt_storage_pool_path} = "$self->{vagrant_cwd}/pool";
63   mkdir $self->{libvirt_storage_pool_path};
64 4 $self->{libvirt_pool_name} = "vagrant" . int(rand(100000));
65 4  
66 4 $vagrant_file_contents .= <<END;
67   config.vm.provider :libvirt do |libvirt|
68 4 libvirt.cpus = $vars->{QEMUCPUS}
69   libvirt.memory = $vars->{QEMURAM}
70   libvirt.storage_pool_name = "$self->{libvirt_pool_name}"
71   end
72   END
73   } else {
74   die "got an unknown vagrant provider $self->{provider}";
75   }
76 1  
77   $vagrant_file_contents .= <<END;
78   end
79 7 END
80    
81   $self->{vagrantfile}->spurt($vagrant_file_contents);
82    
83 7 return $self;
84   }
85 7  
86   my ($retval, $stdin, $stdout, $stderr);
87    
88 31 my @vagrant_cmd = ("vagrant", $args->{cmd});
  31  
  31  
  31  
89 31 push(@vagrant_cmd, ("--machine-readable")) unless $args->{not_machine_readable};
90   push @vagrant_cmd, @{$args->{extra_args}} if defined $args->{extra_args};
91 31 my $timeout = $args->{timeout} // ONE_MINUTE;
92 31  
93 31 bmwqemu::diag("Invoking vagrant command: @vagrant_cmd");
  17  
94 31 {
95   local $CWD = $self->{vagrant_cwd};
96 31 my $handle = IPC::Run::start(\@vagrant_cmd, \$stdin, \$stdout, \$stderr, IPC::Run::timeout($timeout));
97   IPC::Run::finish($handle);
98 31 $retval = $handle->full_result(0);
  31  
99 31 }
100 31  
101 31 return {retval => $retval, stdout => $stdout, stderr => $stderr};
102   }
103    
104 31 my $vagrant_ssh_conf_res = $self->run_vagrant_command({cmd => "ssh-config", not_machine_readable => 1});
105   die "obtaining the ssh config failed!" unless $vagrant_ssh_conf_res->{retval} == 0;
106   my $stdout = $vagrant_ssh_conf_res->{stdout};
107 5 my %con_creds = (
  5  
  5  
108 5 hostname => "localhost",
109 5 username => "vagrant",
110 5 password => "vagrant",
111 5 port => 22
112   );
113    
114   if ($stdout =~ m/\w*HostName (.*)/) {
115   $con_creds{hostname} = $1;
116   }
117   if ($stdout =~ m/\w*User (.*)/) {
118 5 $con_creds{username} = $1;
119 1 }
120   if ($stdout =~ m/\w*Port (\d+)/) {
121 5 $con_creds{port} = $1;
122 1 }
123   return %con_creds;
124 5 }
125 1  
126   if (defined($self->{libvirt_pool_name})) {
127 5 my ($stdout, $stderr, $virsh_res);
128    
129   my @virsh_cmd = ("virsh", "pool-create-as", "--target", $self->{libvirt_storage_pool_path}, "--name", $self->{libvirt_pool_name}, "--type", "dir");
130 5 my $handle = IPC::Run::start(\@virsh_cmd, \undef, \$stdout, \$stderr);
  5  
  5  
131 5 IPC::Run::finish($handle);
132 4 $virsh_res = $handle->full_result(0);
133    
134 4 # don't die in case that the storage pool already exists, but die if
135 4 # there's a different error
136 4 my $re = qr/pool '$self->{libvirt_pool_name}' already exists with uuid/;
137 4 die "Create libvirt storage pool failed with exit code: $virsh_res\n, $stdout\n, $stderr\n"
138   if (($virsh_res != 0) && !($stderr =~ m/$re/));
139   }
140    
141 4 my @prov = ("--provider", $self->{provider});
142 4 my $args = {cmd => "up", extra_args => \@prov, timeout => $self->{up_timeout}};
143    
144   my $res = $self->run_vagrant_command($args);
145   die "Failed to execute vagrant up, got:\n$res->{stdout}\n\n$res->{stderr}\n"
146 4 unless $res->{retval} == 0;
147 4  
148   my %ssh_creds = $self->get_ssh_credentials();
149 4 my $ssh = $testapi::distri->add_console('vagrant-ssh', 'ssh-serial', \%ssh_creds);
150   $ssh->backend($self);
151 4  
152   return {};
153 3 }
154 3  
155 3 my $res = $self->run_vagrant_command({cmd => "halt"});
156   if ($res->{retval} != 0) {
157 3 bmwqemu::fctwarn("vagrant: failed to execute vagrant halt, got $res->{retval},\n$res->{stdout}\n$res->{stderr}");
158   }
159    
160 6 my @extra_args = ("-f");
  6  
  6  
161 6 my $destroy_res = $self->run_vagrant_command({cmd => "destroy", extra_args => \@extra_args});
162 6 if ($destroy_res->{retval} != 0) {
163 1 bmwqemu::fctwarn("vagrant: failed to destroy the vagrant VM, got:\n$destroy_res->{stdout}\n$destroy_res->{stderr}");
164   }
165    
166 6 # ensure that the box is gone:
167 6 my $extra_remove_args = ["remove", "-af", "--provider", $self->{provider}, $self->{box_name}];
168 6 my $box_remove_res = $self->run_vagrant_command({cmd => "box", extra_args => $extra_remove_args});
169 1 if ($box_remove_res->{retval} != 0) {
170   bmwqemu::fctwarn("vagrant: failed to destroy the vagrant box $self->{box_name}, got:\n$box_remove_res->{stdout}\n$box_remove_res->{stderr}");
171   }
172    
173 6 if (defined($self->{libvirt_pool_name})) {
174 6 my ($stdout, $stderr, $virsh_res);
175 6 my @virsh_cmd = ("virsh", "pool-destroy", $self->{libvirt_pool_name});
176 1 my $handle = IPC::Run::start(\@virsh_cmd, \undef, \$stdout, \$stderr);
177   IPC::Run::finish($handle);
178   $virsh_res = $handle->full_result(0);
179 6  
180 5 if ($virsh_res != 0) {
181 5 bmwqemu::fctwarn("vagrant: failed to destroy the libvirt storage pool $self->{libvirt_pool_name}, got $virsh_res\n$stdout\n$stderr");
182 5 }
183 5 }
184 5 }
185    
186 5 my @args = ('--', split(/ /, $cmd));
187 1 my $res = $self->run_vagrant_command({cmd => "ssh", not_machine_readable => 1, extra_args => \@args});
188    
189   chomp $res->{stdout};
190   return $res->{stdout};
191   }
192 1  
  1  
  1  
  1  
193 1  
194 1 my $res = $self->run_vagrant_command({cmd => "status", timeout => 5});
195   chomp($res->{stdout});
196 1 return $res->{stdout} =~ /default,state,(shutoff|not_created|poweroff)/;
197 1 }
198    
199    
200 1  
  1  
201   1;