File Coverage

blib/lib/Tapper/Installer/Precondition.pm
Criterion Covered Total %
statement 34 130 26.1
branch 0 92 0.0
condition 0 9 0.0
subroutine 12 19 63.1
pod n/a
total 46 250 18.4


line stmt bran cond sub pod time code
1             package Tapper::Installer::Precondition;
2             BEGIN {
3 8     8   153216 $Tapper::Installer::Precondition::AUTHORITY = 'cpan:TAPPER';
4             }
5             {
6             $Tapper::Installer::Precondition::VERSION = '4.1.1';
7             }
8              
9 8     8   91 use strict;
  8         50  
  8         351  
10 8     8   61 use warnings;
  8         18  
  8         330  
11 8     8   261 use 5.010;
  8         38  
  8         388  
12              
13 8     8   7233 use Hash::Merge::Simple 'merge';
  8         4868  
  8         743  
14 8     8   11090 use File::Type;
  8         123373  
  8         691  
15 8     8   123 use File::Basename;
  8         17  
  8         963  
16 8     8   1227 use Moose;
  8         626451  
  8         102  
17 8     8   83636 use Socket;
  8         41971  
  8         6256  
18 8     8   4656 use Sys::Hostname;
  8         5360  
  8         477  
19 8     8   5452 use YAML;
  8         64088  
  8         593  
20 8     8   1421 use File::Temp qw/tempdir/;
  8         13314  
  8         14435  
21              
22             extends 'Tapper::Installer';
23              
24              
25              
26              
27             sub get_file_type
28             {
29 0     0     my ($self, $file) = @_;
30 0           my @file_split=split(/\./,$file);
31 0           my $type=$file_split[-1];
32 0 0 0       if ($type eq "iso") {
    0 0        
    0          
    0          
    0          
    0          
33 0           return (0,"iso");
34             } elsif ($type eq "gz" or $type eq "tgz") {
35 0           return (0,"gzip");
36             } elsif ($type eq "tar") {
37 0           return (0,"tar");
38             } elsif ($type eq "bz" or $type eq "bz2") {
39 0           return (0,"bz2");
40             } elsif ($type eq "rpm") {
41 0           return(0,"rpm");
42             } elsif ($type eq "deb") {
43 0           return(0,"deb");
44             }
45              
46 0 0         if (not -e $file) {
47 0           return (0,"$file does not exist. Can't check file type");
48             }
49 0           my $ft = File::Type->new();
50 0           $type = $ft->mime_type("$file");
51 0 0         if ($type eq "application/octet-stream") {
    0          
    0          
    0          
    0          
52 0           my ($error, $output)=$self->log_and_exec("file $file");
53 0 0         return (0, "Getting file type of $file failed: $output") if $error;
54 0 0         return (0,"iso") if $output =~m/ISO 9660/i;
55 0 0         return (0,"rpm") if $output =~m/$file: RPM/i;
56 0 0         return (0,"deb") if $output =~m/$file: Debian/i;
57             } elsif ($type eq "application/x-dpkg") {
58 0           return (0,"deb");
59             } elsif ($type eq "application/x-gzip") {
60 0           return (0,"gzip");
61             } elsif ($type eq "application/x-gtar") {
62 0           return (0,"tar");
63             } elsif ($type eq "application/x-bzip2") {
64 0           return (0,"bz2");
65             } else {
66 0           return(1, "$file is of unrecognised file type \"$type\"");
67             }
68             }
69              
70              
71              
72              
73              
74             sub gethostname
75             {
76 0     0     my ($self) = @_;
77 0           my $hostname = Sys::Hostname::hostname();
78 0 0         if ($hostname =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
79 0 0 0       ($hostname) = gethostbyaddr(inet_aton($hostname), AF_INET) or ( print("Can't get hostname: $!") and exit 1);
80 0           $hostname =~ s/^(\w+?)\..+$/$1/;
81 0           system("hostname", "$hostname");
82             }
83 0           return $hostname;
84             }
85              
86              
87             sub cleanup
88             {
89 0     0     my ($self) = @_;
90 0 0         foreach my $order (@{$self->cfg->{cleanup} || []}) {
  0            
91 0 0         $order->{call}->(@{$order->{options} || []});
  0            
92             }
93 0           return 0;
94             }
95              
96              
97              
98             sub handle_source_url
99             {
100 0     0     my ($self, $precondition) = @_;
101              
102 0 0         if ( $precondition->{source_url} =~ m{^nfs://(.+/)([^/]+)(/?)$} ) {
103 0           my $nfs_dir = tempdir (CLEANUP => 1); # allow to have multiple nfs mount
104 0           $self->log_and_exec("mount","-t nfs","$1", $nfs_dir);
105 0           $precondition->{name} = $precondition->{filename} = "$nfs_dir/$2";
106 0     0     push @{$self->cfg->{cleanup}}, {call => sub {$self->log_and_exec(@_)},
  0            
107 0           options => ['umount',$nfs_dir]};
108             }
109 0           return $precondition;
110             }
111              
112              
113              
114             sub precondition_install
115             {
116 0     0     my ($self, $precondition) = @_;
117              
118 0 0         $precondition = $self->handle_source_url($precondition) if $precondition->{source_url};
119              
120 0           my $retval;
121 0           my ($error, $loop);
122 0 0         $self->makedir($self->cfg->{paths}{guest_mount_dir}) if not -d $self->cfg->{paths}{guest_mount_dir};
123              
124 0           my $image;
125 0           my $partition = $precondition->{mountpartition};
126 0           my $new_base_dir = $self->cfg->{paths}{base_dir};
127              
128 0 0         if ($precondition->{mountfile}) {
    0          
    0          
129 0           $image = $self->cfg->{paths}{base_dir}.$precondition->{mountfile};
130 0           $new_base_dir = $self->cfg->{paths}{guest_mount_dir};
131 0 0         if ( $precondition->{mountpartition} ) {
132             # make sure loop device is free
133             # don't use losetup -f, until it is available on installer NFS root
134 0           $self->log_and_exec("losetup -d /dev/loop0"); # ignore error since most of the time device won't be already bound
135 0 0         return $retval if $retval = $self->log_and_exec("losetup /dev/loop0 $image");
136 0 0         return $retval if $retval = $self->log_and_exec("kpartx -a /dev/loop0");
137 0 0         return $retval if $retval = $self->log_and_exec("mount /dev/mapper/loop0$partition ".$new_base_dir);
138             } else {
139 0 0         return $retval if $retval = $self->log_and_exec("mount -o loop $image ".$new_base_dir);
140             }
141             }
142             elsif ($precondition->{mountpartition}) {
143 0           $new_base_dir = $self->cfg->{paths}{guest_mount_dir};
144 0 0         return $retval if $retval = $self->log_and_exec("mount $partition ".$new_base_dir);
145             }
146             elsif ($precondition->{mountdir}) {
147 0           $new_base_dir .= $precondition->{mountdir};
148             }
149              
150             # call
151 0           my $old_basedir = $self->cfg->{paths}{base_dir};
152 0           $self->cfg->{paths}{base_dir} = $new_base_dir;
153 0 0         return $retval if $retval=$self->install($precondition);
154              
155              
156 0 0         if ($precondition->{mountfile}) {
    0          
157 0 0         if ( $precondition->{mountpartition} ) {
158 0 0         return $retval if $retval = $self->log_and_exec("umount /dev/mapper/loop0$partition");
159 0 0         return $retval if $retval = $self->log_and_exec("kpartx -d /dev/loop0");
160 0 0         if ($retval = $self->log_and_exec("losetup -d /dev/loop0")) {
161 0           sleep (2);
162 0 0         return $retval if $retval = $self->log_and_exec("kpartx -d /dev/loop0");
163 0 0         return $retval if $retval = $self->log_and_exec("losetup -d /dev/loop0");
164             }
165             } else {
166 0           $retval = $self->log_and_exec("umount $new_base_dir");
167 0 0         $self->log->error("Can not unmount $new_base_dir: $retval") if $retval;
168              
169             # seems like mount -o loop uses a loop device that is not freed at umount
170 0           $self->log_and_exec("kpartx -d /dev/loop0");
171 0           $self->log_and_exec("losetup -d /dev/loop0");
172             }
173             }
174             elsif ($precondition->{mountpartition}) {
175 0           $retval = $self->log_and_exec("umount $new_base_dir");
176 0 0         $self->log->error("Can not unmount $new_base_dir: $retval") if $retval;
177             }
178 0           $self->cleanup();
179 0           $self->cfg->{paths}{base_dir} = $old_basedir;
180 0           return 0;
181              
182             }
183              
184              
185              
186             sub file_save
187             {
188 0     0     my ($self, $output, $filename) = @_;
189 0           my $testrun_id = $self->cfg->{test_run};
190 0           my $destdir = $self->cfg->{paths}{output_dir}."/$testrun_id/install/";
191 0           my $destfile = $destdir."/$filename";
192 0 0         if (not -d $destdir) {
193 0 0         system("mkdir","-p",$destdir) == 0 or return ("Can't create $destdir:$!");
194             }
195 0 0         open(my $FH,">",$destfile)
196             or return ("Can't open $destfile:$!");
197 0           print $FH $output;
198 0           close $FH;
199             }
200              
201              
202              
203             1;
204              
205             __END__
206             =pod
207              
208             =encoding utf-8
209              
210             =head1 NAME
211              
212             Tapper::Installer::Precondition
213              
214             =head1 SYNOPSIS
215              
216             use Tapper::Installer::Precondition;
217              
218             =head1 NAME
219              
220             Tapper::Installer::Precondition - Base class with common functions
221             for Tapper::Installer::Precondition modules
222              
223             =head1 FUNCTIONS
224              
225             =head2 get_file_type
226              
227             Return the file type of a given file. "rpm, "deb", "tar", "gzip", "bz2" and
228             "iso" 9660 cd images are recognised at the moment. If file does not exists at
229             the given file name, only suffix analysis will be available. To enforce any of
230             the above mentioned types, just set the suffix of the file accordingly.
231              
232             @param string - file name
233              
234             @returnlist success - (0, rpm|deb|iso|tar|gzip|bzip2)
235             @returnlist error - (1, error string)
236              
237             =head2 gethostname
238              
239             This function returns the host name of the machine. When NFS root is
240             used together with DHCP the hostname set in the kernel usually equals
241             the IP address received from DHCP as a string. In this case the kernel
242             hostname is set to the DNS hostname associated to this IP address.
243              
244             @return hostname of the machine as set in the kernel
245              
246             =head2 cleanup
247              
248             Clean up all remaining preparations (given in config).
249              
250             @return success - 0
251             @return error - error string
252              
253             =head2 handle_source_url
254              
255             A preconditions source may need some preparation, e.g. if it's located
256             on an NFS share we need to mount this share. This function handles these
257             preparations.
258              
259             @param hash ref - precondition
260              
261             @return success - hash ref with updated precondition
262             @return error - error string
263              
264             =head2 precondition_install
265              
266             Install a precondition with preparations up front. This could be
267             mounting an NFS share or installing inside a virtualisation guest or
268             even no preparation at all.
269              
270             A guest can be given as image, partition or directory. This function
271             makes the necessary preparations, calls the right precondition install
272             function and cleans up afterwards. An image can be given as file name
273             and partition or file name only. The later is supposed to be an image
274             file containing just one partition.
275              
276             @param hash ref - precondition
277              
278             @return success - 0
279             @return error - error string
280              
281             =head2 file_save
282              
283             Save output as file for MCP to find it and upload it to reports receiver.
284              
285             @param string - output to be written to file
286             @param string - basename of the file to write output to
287              
288             @return success - 0
289             @return errorr - error string
290              
291             =head1 AUTHOR
292              
293             AMD OSRC Tapper Team <tapper@amd64.org>
294              
295             =head1 COPYRIGHT AND LICENSE
296              
297             This software is Copyright (c) 2012 by Advanced Micro Devices, Inc..
298              
299             This is free software, licensed under:
300              
301             The (two-clause) FreeBSD License
302              
303             =cut
304