File Coverage

blib/lib/Tapper/Installer/Precondition/Exec.pm
Criterion Covered Total %
statement 29 80 36.2
branch 2 26 7.6
condition 0 5 0.0
subroutine 9 10 90.0
pod n/a
total 40 121 33.0


line stmt bran cond sub pod time code
1             package Tapper::Installer::Precondition::Exec;
2             BEGIN {
3 2     2   138607 $Tapper::Installer::Precondition::Exec::AUTHORITY = 'cpan:TAPPER';
4             }
5             {
6             $Tapper::Installer::Precondition::Exec::VERSION = '4.1.1';
7             }
8              
9 2     2   59 use 5.010;
  2         8  
  2         76  
10 2     2   11 use strict;
  2         5  
  2         62  
11 2     2   10 use warnings;
  2         4  
  2         72  
12              
13 2     2   2062 use Moose;
  2         1206153  
  2         19  
14 2     2   17354 use IO::Handle; # needed to set pipe nonblocking
  2         6  
  2         141  
15 2     2   545054 use IO::Select;
  2         5589  
  2         201  
16 2     2   2755 use Linux::Personality qw/personality PER_LINUX32 /;
  2         64439  
  2         2225  
17              
18             extends 'Tapper::Installer::Precondition';
19              
20              
21              
22              
23             sub set_env_variables
24             {
25 0     0   0 my ($self) = @_;
26              
27 0         0 $ENV{TAPPER_TESTRUN} = $self->cfg->{test_run};
28 0         0 $ENV{TAPPER_SERVER} = $self->cfg->{mcp_host};
29 0         0 $ENV{TAPPER_REPORT_SERVER} = $self->cfg->{report_server};
30 0         0 $ENV{TAPPER_REPORT_API_PORT} = $self->cfg->{report_api_port};
31 0         0 $ENV{TAPPER_REPORT_PORT} = $self->cfg->{report_port};
32 0         0 $ENV{TAPPER_HOSTNAME} = $self->cfg->{hostname};
33 0         0 return;
34             }
35              
36              
37             sub install
38             {
39 1     1   5621 my ($self, $exec) = @_;
40              
41 1         4 my $command = $exec->{command};
42 1         2 my @options;
43 1 50       7 @options = @{$exec->{options}} if $exec->{options};
  1         5  
44              
45 1 50       4 if ($exec->{filename}) {
46 0         0 $command = $exec->{filename};
47 0         0 my $cmd_full = $self->cfg->{paths}{base_dir}.$command;
48 0 0       0 if (not -x $cmd_full) {
49 0         0 $self->log_and_exec ("chmod", "ugo+x", $cmd_full);
50 0 0       0 return("tried to execute $cmd_full which is not an execuable and can not set exec flag") if not -x $cmd_full;
51             }
52             }
53              
54 1         165 $self->log->debug("executing $command with options ",join (" ",@options));
55              
56              
57 0           pipe (my $read, my $write);
58 0 0 0       return ("Can't open pipe:$!") if not (defined $read and defined $write);
59              
60             # we need to fork for chroot
61 0           my $pid = fork();
62 0 0         return "fork failed: $!" if not defined $pid;
63              
64             # hello child
65 0 0         if ($pid == 0) {
66 0           $self->set_env_variables;
67              
68 0           close $read;
69             # chroot to execute script inside the future root file system
70 0           my ($error, $output) = $self->log_and_exec("mount -o bind /dev/ ".$self->cfg->{paths}{base_dir}."/dev");
71 0           ($error, $output) = $self->log_and_exec("mount -t sysfs sys ".$self->cfg->{paths}{base_dir}."/sys");
72 0           ($error, $output) = $self->log_and_exec("mount -t proc proc ".$self->cfg->{paths}{base_dir}."/proc");
73 0   0       my $arch = $exec->{arch} // "";
74 0 0         personality(PER_LINUX32) if $arch eq 'linux32';
75 0           chroot $self->cfg->{paths}{base_dir};
76 0           chdir ("/");
77 0 0         %ENV = (%ENV, %{$exec->{environment} || {} });
  0            
78 0           ($error, $output)=$self->log_and_exec($command,@options);
79 0 0         print( $write $output, "\n") if $output;
80 0           close $write;
81 0           exit $error;
82             } else {
83 0           close $write;
84 0           my $select = IO::Select->new( $read );
85 0           my ($error, $output);
86             MSG_FROM_CHILD:
87 0           while (my @ready = $select->can_read()){
88 0           my $tmpout = <$read>; # only read can be in @ready, since no other FH is in $select
89 0 0         last MSG_FROM_CHILD if not $tmpout;
90 0           $output.=$tmpout;
91             }
92 0 0         if ($output) {
93 0           my $outfile = $command;
94 0           $outfile =~ s/[^A-Za-z_-]/_/g;
95 0           $self->file_save($output,$outfile);
96             }
97 0           ($error, $output)=$self->log_and_exec("umount ".$self->cfg->{paths}{base_dir}."/dev");
98 0           ($error, $output)=$self->log_and_exec("umount ".$self->cfg->{paths}{base_dir}."/sys");
99 0           ($error, $output)=$self->log_and_exec("umount ".$self->cfg->{paths}{base_dir}."/proc");
100 0           waitpid($pid,0);
101 0 0         if ($?) {
102 0           return("executing $command failed");
103             }
104 0           return(0);
105             }
106             }
107              
108              
109              
110             1;
111              
112             __END__
113             =pod
114              
115             =encoding utf-8
116              
117             =head1 NAME
118              
119             Tapper::Installer::Precondition::Exec
120              
121             =head1 SYNOPSIS
122              
123             use Tapper::Installer::Precondition::Exec;
124              
125             =head1 NAME
126              
127             Tapper::Installer::Precondition::Exec - Execute a program inside the installed system
128              
129             =head1 FUNCTIONS
130              
131             =head2 set_env_variables
132              
133             Set environment variables for executed command/program.
134              
135             =head2 install
136              
137             This function executes a program inside the installed system. This supersedes
138             the postinstall script facility of the package precondition and makes this
139             feature available to all other preconditions.
140              
141             @param hash reference - contains all information about the program
142              
143             @return success - 0
144             @return error - error string
145              
146             =head1 AUTHOR
147              
148             AMD OSRC Tapper Team <tapper@amd64.org>
149              
150             =head1 COPYRIGHT AND LICENSE
151              
152             This software is Copyright (c) 2012 by Advanced Micro Devices, Inc..
153              
154             This is free software, licensed under:
155              
156             The (two-clause) FreeBSD License
157              
158             =cut
159