File Coverage

blib/lib/Tapper/Installer/Precondition/Exec.pm
Criterion Covered Total %
statement 42 76 55.2
branch 9 26 34.6
condition 1 5 20.0
subroutine 7 8 87.5
pod 2 2 100.0
total 61 117 52.1


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