| 223 | rodolico | 1 | #! /usr/bin/env perl
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | use strict;
 | 
        
           |  |  | 4 | use warnings;
 | 
        
           |  |  | 5 |   | 
        
           |  |  | 6 |   | 
        
           |  |  | 7 | # find our location and use it for searching for libraries
 | 
        
           |  |  | 8 | BEGIN {
 | 
        
           |  |  | 9 |    use FindBin;
 | 
        
           |  |  | 10 |    use File::Spec;
 | 
        
           |  |  | 11 |    # use libraries from the directory this script is in
 | 
        
           |  |  | 12 |    use lib File::Spec->catdir($FindBin::Bin);
 | 
        
           |  |  | 13 |    # and its parent
 | 
        
           |  |  | 14 |    use lib File::Spec->catdir( $FindBin::Bin . '/../' );
 | 
        
           |  |  | 15 |    eval( 'use YAML::Tiny' );
 | 
        
           |  |  | 16 | }
 | 
        
           |  |  | 17 |   | 
        
           |  |  | 18 | use Cwd qw(abs_path);
 | 
        
           |  |  | 19 |   | 
        
           |  |  | 20 | my $scriptDir = abs_path(File::Spec->catdir($FindBin::Bin) );
 | 
        
           |  |  | 21 |   | 
        
           |  |  | 22 | use Digest::MD5 qw(md5_hex);
 | 
        
           |  |  | 23 | use File::Copy;
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | # define the version number
 | 
        
           |  |  | 26 | # see https://metacpan.org/pod/release/JPEACOCK/version-0.97/lib/version.pod
 | 
        
           |  |  | 27 | use version;
 | 
        
           |  |  | 28 | our $VERSION = version->declare("v0.001.001");
 | 
        
           |  |  | 29 |   | 
        
           |  |  | 30 |   | 
        
           |  |  | 31 | use Data::Dumper;
 | 
        
           |  |  | 32 | use File::Basename;
 | 
        
           |  |  | 33 | use Getopt::Long;
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 | # load the definitions from installer_config.pl
 | 
        
           |  |  | 36 | do "$scriptDir/installer_config.pl";
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 | our %libraries;
 | 
        
           |  |  | 39 | our %install;
 | 
        
           |  |  | 40 | our %binaries;
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 | use sysinfosetup;
 | 
        
           |  |  | 43 |   | 
        
           |  |  | 44 | Getopt::Long::Configure ("bundling"); # allow -vd --os='debian'
 | 
        
           |  |  | 45 | our $dryRun = 0;
 | 
        
           |  |  | 46 | my $os;
 | 
        
           |  |  | 47 | my $help = 0;
 | 
        
           |  |  | 48 | my $version = 0;
 | 
        
           |  |  | 49 | my $quiet = 0;
 | 
        
           |  |  | 50 | our $DEBUG = 0;
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 | my %commands; # we will use this to track commands that are to be run
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 | # simple display if --help is passed
 | 
        
           |  |  | 55 | sub help {
 | 
        
           |  |  | 56 |    use File::Basename;
 | 
        
           |  |  | 57 |    print basename($0) . " $VERSION\n";
 | 
        
           |  |  | 58 |    print <<END
 | 
        
           |  |  | 59 | $0 [options]
 | 
        
           |  |  | 60 | Options:
 | 
        
           |  |  | 61 |    --os|-o      - lower case name of operating system (debian, freebsd, etc...)
 | 
        
           |  |  | 62 |    --dryrun|-n  - do not actually do anything, just tell you what I'd do
 | 
        
           |  |  | 63 |    --version|-v - display version and exit
 | 
        
           |  |  | 64 |    --quiet|-q   - Do not ask questions, just do stuff
 | 
        
           |  |  | 65 |    --debug      - turn on debug mode (no short form). --nodebug turns off (default)
 | 
        
           |  |  | 66 |    --help|-h    - Show this screen
 | 
        
           |  |  | 67 |   | 
        
           |  |  | 68 | END
 | 
        
           |  |  | 69 | }
 | 
        
           |  |  | 70 |   | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 | # validates the libraries needed exist
 | 
        
           |  |  | 74 | # simply eval's each library. If it doesn't exist, creates a list of
 | 
        
           |  |  | 75 | # commands to be executed to install it, and displays missing libraries
 | 
        
           |  |  | 76 | # offering to install them if possible.
 | 
        
           |  |  | 77 | sub validateLibraries {
 | 
        
           |  |  | 78 |    my ( $libraries, $os, $commands ) = @_;
 | 
        
           |  |  | 79 |    &logIt( 'Entering validateLibraries' );
 | 
        
           |  |  | 80 |    my %return;
 | 
        
           |  |  | 81 |    foreach my $lib ( keys %$libraries ) {
 | 
        
           |  |  | 82 |       &logIt( "Checking on library $lib" );
 | 
        
           |  |  | 83 |       eval( "use $lib;" );
 | 
        
           |  |  | 84 |       if ( $@ ) {
 | 
        
           |  |  | 85 |          print "Needing library $lib\n" if $DEBUG;
 | 
        
           |  |  | 86 |          $return{ $lib } = $libraries->{$lib}->{$os} ? $libraries->{$lib}->{$os} : 'UNK';
 | 
        
           |  |  | 87 |          push @{$commands->{$libraries->{$lib}->{$os}->{'command'}}}, $libraries->{$lib}->{$os}->{'parameter'}
 | 
        
           |  |  | 88 |       }
 | 
        
           |  |  | 89 |    }
 | 
        
           |  |  | 90 |    return \%return;
 | 
        
           |  |  | 91 | } # validateLibraries
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |   | 
        
           |  |  | 94 | # check for any required binaries
 | 
        
           |  |  | 95 | sub validateBinaries {
 | 
        
           |  |  | 96 |    my ( $binaries, $os, $commands ) = @_;
 | 
        
           |  |  | 97 |    &logIt( 'Entering validateBinaries' );
 | 
        
           |  |  | 98 |    my %return;
 | 
        
           |  |  | 99 |    foreach my $bin ( keys %$binaries ) {
 | 
        
           |  |  | 100 |       unless ( `which $bin` ) {
 | 
        
           |  |  | 101 |          print "Needing $bin\n" if $DEBUG;
 | 
        
           |  |  | 102 |          $return{$bin} = $binaries->{$bin}->{$os} ? $binaries->{$bin}->{$os} : 'UNK';
 | 
        
           |  |  | 103 |          push @{$commands->{$binaries->{$bin}->{$os}->{'command'}}}, $binaries->{$bin}->{$os}->{'parameter'}
 | 
        
           |  |  | 104 |       }
 | 
        
           |  |  | 105 |    }
 | 
        
           |  |  | 106 |    return \%return;
 | 
        
           |  |  | 107 | } # validateBinaries
 | 
        
           |  |  | 108 |   | 
        
           |  |  | 109 | ################################################################
 | 
        
           |  |  | 110 | # validateCPAN
 | 
        
           |  |  | 111 | #
 | 
        
           |  |  | 112 | # some of the systems will need to run cpan to get some perl modules.
 | 
        
           |  |  | 113 | # this will go through each of them and see if command starts with cpan
 | 
        
           |  |  | 114 | # and, if so, will check that cpan is installed and configured for root.
 | 
        
           |  |  | 115 | #
 | 
        
           |  |  | 116 | # when cpan is installed, it requires one manual run as root from the cli
 | 
        
           |  |  | 117 | # to determine where to get the files. If that is not done, cpan can not
 | 
        
           |  |  | 118 | # be controlled by a program. We check to see if cpan is installed, then
 | 
        
           |  |  | 119 | # verify /root/.cpan has been created by the configuration tool
 | 
        
           |  |  | 120 | ################################################################
 | 
        
           |  |  | 121 |   | 
        
           |  |  | 122 |   | 
        
           |  |  | 123 | sub validateCPAN {
 | 
        
           |  |  | 124 |    my $libraries = shift;
 | 
        
           |  |  | 125 |    my $needCPAN = 0;
 | 
        
           |  |  | 126 |    my $message = '';
 | 
        
           |  |  | 127 |    foreach my $app ( keys %$libraries ) {
 | 
        
           |  |  | 128 |       if ( $libraries->{$app}->{'command'} =~ m/^cpan/ ) {
 | 
        
           |  |  | 129 |          $needCPAN = 1;
 | 
        
           |  |  | 130 |          last;
 | 
        
           |  |  | 131 |       }
 | 
        
           |  |  | 132 |    }
 | 
        
           |  |  | 133 |    return $message unless $needCPAN;
 | 
        
           |  |  | 134 |    if ( `which cpan` ) {
 | 
        
           |  |  | 135 |       $message =  "****ERROR****\nWe need cpan, and it is installed, but not configured\nrun cpan as root one time to configure it\n" unless -d '/root/.cpan';
 | 
        
           |  |  | 136 |    } else {
 | 
        
           |  |  | 137 |       $message =  'In order to install on this OS, we need cpan, which should have been installed with perl.' .
 | 
        
           |  |  | 138 |           " Can not continue until cpan is installed and configured\n";
 | 
        
           |  |  | 139 |    }
 | 
        
           |  |  | 140 |    return $message;
 | 
        
           |  |  | 141 | }
 | 
        
           |  |  | 142 |   | 
        
           |  |  | 143 |   | 
        
           |  |  | 144 | ################################################################
 | 
        
           |  |  | 145 | #               Main Code                                      #
 | 
        
           |  |  | 146 | ################################################################
 | 
        
           |  |  | 147 |   | 
        
           |  |  | 148 | # handle any command line parameters that may have been passed in
 | 
        
           |  |  | 149 |   | 
        
           |  |  | 150 | GetOptions (
 | 
        
           |  |  | 151 |             "os|o=s"      => \$os,      # pass in the operating system
 | 
        
           |  |  | 152 |             "dryrun|n"    => \$dryRun,  # do NOT actually do anything
 | 
        
           |  |  | 153 |             'help|h'      => \$help,
 | 
        
           |  |  | 154 |             'version|v'   => \$version,
 | 
        
           |  |  | 155 |             'quiet|q'     => \$quiet,
 | 
        
           |  |  | 156 |             'debug!'      => \$DEBUG
 | 
        
           |  |  | 157 |             ) or die "Error parsing command line\n";
 | 
        
           |  |  | 158 |   | 
        
           |  |  | 159 | if ( $help ) { &help() ; exit; }
 | 
        
           |  |  | 160 | if ( $version ) { use File::Basename; print basename($0) . " $VERSION\n"; exit; }
 | 
        
           |  |  | 161 |   | 
        
           |  |  | 162 | die "Can not continue without operating system parameter (--os=)\n" unless $os;
 | 
        
           |  |  | 163 |   | 
        
           |  |  | 164 | &logIt( "Inside validateDependencies" );
 | 
        
           |  |  | 165 | print "Inside validateDependencies\n";
 | 
        
           |  |  | 166 |   | 
        
           |  |  | 167 | # check libraries necessary are loaded, and if not, track the ones we need
 | 
        
           |  |  | 168 | $install{'missing libraries'} = &validateLibraries( \%libraries, $os, \%commands );
 | 
        
           |  |  | 169 | &logIt( "Missing Libraries\n" . Dumper( $install{'missing libraries'} ) );
 | 
        
           |  |  | 170 |   | 
        
           |  |  | 171 | # Check that required binaries are installed and create list of the ones we need
 | 
        
           |  |  | 172 | $install{'missing binaries'} = &validateBinaries( \%binaries, $os, \%commands );
 | 
        
           |  |  | 173 | &logIt( "Missing binaries\n" . Dumper( $install{'missing binaries'} ) );
 | 
        
           |  |  | 174 |   | 
        
           |  |  | 175 | # if we need libraries and the os needs to use CPAN, validate CPAN
 | 
        
           |  |  | 176 | my $cpanMessage = &validateCPAN( $install{'missing libraries'} ) if ( $install{'missing libraries'} );
 | 
        
           |  |  | 177 |   | 
        
           |  |  | 178 | if ( %commands ) {
 | 
        
           |  |  | 179 |    print "We need the following libraries\n" . join( "\n", keys( %{ $install{'missing libraries'} } ) ) . "\n" if $install{'missing libraries'};
 | 
        
           |  |  | 180 |    print "We need the following binaries\n" . join( "\n", keys( %{ $install{'missing binaries'} } ) ) . "\n" if $install{'missing binaries'};
 | 
        
           |  |  | 181 |    print "I can install them with the following command(s)\n";
 | 
        
           |  |  | 182 |   | 
        
           |  |  | 183 |    my @commandList;
 | 
        
           |  |  | 184 |    foreach my $command ( keys %commands ) {
 | 
        
           |  |  | 185 |       push @commandList,  $command . ' ' . join( ' ', @{$commands{$command}} );
 | 
        
           |  |  | 186 |    }
 | 
        
           |  |  | 187 |    print join( "\n", @commandList ) . "\n";
 | 
        
           |  |  | 188 |    if ( $cpanMessage ) {
 | 
        
           |  |  | 189 |       print "However, $cpanMessage\nExiting\n";
 | 
        
           |  |  | 190 |       return 2;
 | 
        
           |  |  | 191 |    }
 | 
        
           |  |  | 192 |    if ( $quiet || &yesno( "Do you want me to run these commands?" ) ) {
 | 
        
           |  |  | 193 |       for ( my $i = 0; $i < @commandList; $i++ ) {
 | 
        
           |  |  | 194 |          &runCommand( $commandList[$i] ) || die "Error executing $commandList[$i]\n";
 | 
        
           |  |  | 195 |       }
 | 
        
           |  |  | 196 |    }
 | 
        
           |  |  | 197 | }
 | 
        
           |  |  | 198 | 1;
 |