Subversion Repositories camp_sysinfo_client_3

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
101 rodolico 1
#! /usr/bin/env perl
2
 
3
use strict;
4
use warnings;
5
 
132 rodolico 6
# install.pl
7
#
8
# installer for perl script, in this case, sysinfo
9
#
10
# Revision history
11
#
12
# Version 1.1.7 20161010 RWR
13
# Added ability to validate required libraries are installed
14
#
15
# version 1.2 20170327 RWR
16
# did some major modifications to correctly work on BSD systems also
17
#
18
# version 2.0 20190330 RWR
19
# changed it so all configs are YAML
20
#
21
# version 3.0 20191105 RWR
22
# set up so all options are presented on initial screen
23
# user can choose options to edit
24
# rest of install is automatic
138 rodolico 25
#
26
# version 3.1 20191112 RWR
27
# Added logging. Log file will be written to the install directory with
28
# the application name.log as the name (application name taken from installer_config.pl)
144 rodolico 29
#
30
# version 3.1.1 20191117 RWR
31
# Added the ability to verify cpan is installed and configured on systems which need it
32
#
156 rodolico 33
# version 3.1.2 20200215 RWR
34
# Adding version comparisons
210 rodolico 35
#
36
# version 3.3.0 20230308 RWR
211 rodolico 37
# major revision. Allows --quiet (don't ask questions). Correctly handles when the source has been installed via a
210 rodolico 38
# separate process. Mainly designed to allow checkout from svn repository.
101 rodolico 39
 
132 rodolico 40
# find our location and use it for searching for libraries
41
BEGIN {
42
   use FindBin;
43
   use File::Spec;
203 rodolico 44
   # use libraries from the directory this script is in
132 rodolico 45
   use lib File::Spec->catdir($FindBin::Bin);
203 rodolico 46
   # and its parent
47
   use lib File::Spec->catdir( $FindBin::Bin . '/../' );
132 rodolico 48
   eval( 'use YAML::Tiny' );
49
}
50
 
211 rodolico 51
use Cwd qw(abs_path);
101 rodolico 52
 
211 rodolico 53
my $installerDir = abs_path(File::Spec->catdir($FindBin::Bin) );
54
my $sourceDir = abs_path($installerDir . '/..');
55
 
156 rodolico 56
use Digest::MD5 qw(md5_hex);
208 rodolico 57
use File::Copy;
156 rodolico 58
 
59
# define the version number
60
# see https://metacpan.org/pod/release/JPEACOCK/version-0.97/lib/version.pod
61
use version;
210 rodolico 62
our $VERSION = version->declare("v3.003.000");
156 rodolico 63
 
64
 
132 rodolico 65
use Data::Dumper;
66
use File::Basename;
67
use Getopt::Long;
101 rodolico 68
 
132 rodolico 69
our %install;
70
our %operatingSystems;
71
our %libraries;
72
our %binaries;
206 rodolico 73
# load the definitions from installer_config.pl
211 rodolico 74
do "$installerDir/installer_config.pl";
138 rodolico 75
#
76
# set up log file
77
my $logFile = $install{'application name'};
78
$logFile =~ s/ /_/g;
211 rodolico 79
$logFile = "$installerDir/$logFile.log";
132 rodolico 80
 
81
Getopt::Long::Configure ("bundling"); # allow -vd --os='debian'
82
my $dryRun = 0;
83
my $os;
84
my $help = 0;
85
my $version = 0;
206 rodolico 86
my $quiet = 0;
132 rodolico 87
 
88
my @messages; # stores any messages we want to show up at the end
89
my @feedback; # store feedback when we execute command line actions
90
 
91
my %configuration;
92
 
93
# simple display if --help is passed
94
sub help {
95
   my $oses = join( ' ', keys %operatingSystems );
156 rodolico 96
   use File::Basename;
97
   print basename($0) . " $VERSION\n";
132 rodolico 98
   print <<END
156 rodolico 99
$0 [options]
100
Options:
101
   --os      - osname is one of [$oses]
102
   --dryrun  - do not actually do anything, just tell you what I'd do
103
   --version - display version and exit
206 rodolico 104
   --quiet   - Do not ask questions, just do stuff
105
 
106
For an inplace upgrade, it is assumed the source code has been
107
downloaded and installed into the correct directories already
132 rodolico 108
END
101 rodolico 109
}
110
 
138 rodolico 111
#######################################################
144 rodolico 112
#
113
# timeStamp
114
#
115
# return current system date as YYYY-MM-DD HH:MM:SS
116
#
117
#######################################################
118
sub timeStamp {
119
   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
120
   return sprintf "%4d-%02d-%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;
121
}
122
 
123
sub yesno {
124
   my ( $prompt, $default ) = @_;
125
   $default = 'yes' unless $default;
126
   my $answer = &getAnswer( $prompt, $default eq 'yes' ? ('yes','no' ) : ('no', 'yes') );
127
   return lc( substr( $answer, 0, 1 ) ) eq 'y';
128
}
129
 
130
# prompt the user for a response, then allow them to enter it
131
# the first response is considered the default and is printed
132
# in all caps if more than one exists
133
# first answer is used if they simply press the Enter
134
# key. The response is returned all lower case if more than one
135
# exists.
136
# it is assumed 
137
sub getAnswer {
138
   my ( $prompt, @answers ) = @_;
139
   $answers[0] = '' unless defined( $answers[0] );
140
   my $default = $answers[0];
141
   my $onlyOneAnswer = scalar( @answers ) == 1;
142
   print $prompt . '[ ';
143
   $answers[0] = uc $answers[0] unless $onlyOneAnswer;
144
   print join( ' | ', @answers ) . ' ]: ';
145
   my $thisAnswer = <>;
146
   chomp $thisAnswer;
147
   $thisAnswer = $default unless $thisAnswer;
148
   return $thisAnswer;
149
}
150
 
151
 
152
#######################################################
138 rodolico 153
# function to simply log things
154
# first parameter is the priority, if <= $logDef->{'log level'} will print
155
# all subsequent parameters assumed to be strings to sent to the log
156
# returns 0 on failure
157
#         1 on success
158
#         2 if priority > log level
159
#        -1 if $logDef is unset
160
# currently, only logs to a file
161
#######################################################
162
sub logIt {
140 rodolico 163
   open LOG, ">>$logFile" or die "Could not append to $logFile: $!\n";
138 rodolico 164
   while ( my $t = shift ) {
165
      print LOG &timeStamp() . "\t$t\n";
166
   }
167
   close LOG;
168
   return 1;
169
}
101 rodolico 170
 
138 rodolico 171
 
132 rodolico 172
# attempt to locate the operating system.
173
# if found, will set some defaults for it.
174
sub setUpOperatingSystemSpecific {
175
   my ( $install, $operatingSystems, $os, $installDir ) = @_;
138 rodolico 176
   &logIt( 'Entering setUpOperatingSystemSpecific' );
177
   &logIt( "They passed $os in as the \$os" );
132 rodolico 178
   if ( $os ) {
179
      # We found the OS, set up some defaults
180
      $$install{'os'} = $os;
138 rodolico 181
      &logIt( "Setting keys for operating system" );
132 rodolico 182
      # merge operatingSystems into install
183
      foreach my $key ( keys %{$operatingSystems->{$os}} ) {
184
         if ( $key eq 'files' ) {
185
            $install->{'files'} = { %{$install->{'files'}}, %{$operatingSystems->{$os}->{'files'}} }
186
         } else {
187
            $install->{$key} = $operatingSystems->{ $os }->{$key};
188
         }
189
      } # if it is a known OS
190
   } # if
191
   return $os;
192
} # getOperatingSystem
193
 
194
# validates the libraries needed exist
195
# simply eval's each library. If it doesn't exist, creates a list of
196
# commands to be executed to install it, and displays missing libraries
197
# offering to install them if possible.
198
sub validateLibraries {
199
   my ( $libraries, $os ) = @_;
138 rodolico 200
   &logIt( 'Entering validateLibraries' );
132 rodolico 201
   my %return;
202
   foreach my $lib ( keys %$libraries ) {
138 rodolico 203
      &logIt( "Checking on library $lib" );
132 rodolico 204
      eval( "use $lib;" );
205
      if ( $@ ) {
206
         $return{ $lib } = $libraries->{$lib}->{$os} ? $libraries->{$lib}->{$os} : 'UNK';
207
      }
208
   }
209
   return \%return;
210
} # validateLibraries
211
 
212
 
213
# check for any required binaries
214
sub validateBinaries {
215
   my ( $binaries, $os ) = @_;
138 rodolico 216
   &logIt( 'Entering validateBinaries' );
132 rodolico 217
   my %return;
218
   foreach my $bin ( keys %$binaries ) {
219
      unless ( `which $bin` ) {
220
         $return{$bin} = $binaries->{$bin}->{$os} ? $binaries->{$bin}->{$os} : 'UNK';
221
      }
222
   }
223
   return \%return;
224
} # validateBinaries
225
 
226
# get some input from the user and decide how to install/upgrade/remove/whatever
227
sub getInstallActions {
228
   my $install = shift;
138 rodolico 229
   &logIt( 'Entering getInstallActions' );
132 rodolico 230
   if ( -d $install->{'confdir'} ) {
231
      $install->{'action'} = "upgrade";
232
   } else {
233
      $install->{'action'} = 'install';
234
   }
235
   $install->{'build config'} = 'Y';
236
   $install->{'setup cron'} = 'Y';
101 rodolico 237
}
238
 
132 rodolico 239
# locate all items in $hash which have one of the $placeholder elements in it
240
# and replace, ie <binddir> is replaced with the actual binary directory
241
sub doPlaceholderSubstitution {
242
   my ($hash, $placeholder) = @_;
138 rodolico 243
   &logIt( 'Entering doPlaceholderSubstitution' );
132 rodolico 244
   return if ref $hash ne 'HASH';
245
   foreach my $key ( keys %$hash ) {
246
      if ( ref( $$hash{$key} ) ) {
247
         &doPlaceholderSubstitution( $$hash{$key}, $placeholder );
248
      } else {
249
         foreach my $place ( keys %$placeholder ) {
250
            $$hash{$key} =~ s/$place/$$placeholder{$place}/;
251
         } # foreach
252
      } # if..else
253
   } # foreach
254
   return;
255
}
256
 
257
# This will go through and first, see if anything is a directory, in
258
# which case, we'll create new entries for all files in there.
259
# then, it will do keyword substitution of <bindir> and <confdir>
260
# to populate the target.
261
# When this is done, each file should have a source and target that is
262
# a fully qualified path and filename
208 rodolico 263
sub massageInstallValues {
132 rodolico 264
   my ( $install, $sourceDir ) = @_;
211 rodolico 265
   &logIt( 'Entering massageInstallValues' );
132 rodolico 266
   my %placeHolders = 
267
      ( 
268
        '<bindir>' => $$install{'bindir'},
269
        '<confdir>' => $$install{'confdir'},
270
        '<default owner>' => $$install{'default owner'},
271
        '<default group>' => $$install{'default group'},
272
        '<default permission>' => $$install{'default permission'},
273
        '<installdir>' => $sourceDir
274
      );
101 rodolico 275
 
132 rodolico 276
   my $allFiles = $$install{'files'};
101 rodolico 277
 
132 rodolico 278
   # find all directory entries and load files in that directory into $$install{'files'}
279
   foreach my $dir ( keys %$allFiles ) {
280
      if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
138 rodolico 281
         &logIt( "Found directory $dir" );
132 rodolico 282
         if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
283
            my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
138 rodolico 284
            &logIt( "\tFound files " . join( ' ', @files ) );
132 rodolico 285
            foreach my $file ( @files ) {
286
               $$allFiles{ $file }{'type'} = 'file';
287
               if ( $dir eq 'modules' ) {
288
                  $$allFiles{ $file }{'permission'} = ( $file =~ m/$$install{'modules'}/ ) ? '0700' : '0600';
289
               } else {
290
                  $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
291
               }
292
               $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
293
               $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
294
            } # foreach
295
            closedir $dh;
296
         } # if opendir
297
      } # if it is a directory
298
   } # foreach
299
   # find all files, and set the source directory, and add the filename to
300
   # the target
301
   foreach my $file ( keys %$allFiles ) {
302
      $$allFiles{$file}{'source'} = "$sourceDir/$file";
303
      $$allFiles{$file}{'target'} .= "/$file";
304
   } # foreach
101 rodolico 305
 
132 rodolico 306
   # finally, do place holder substitution. This recursively replaces all keys
307
   # in  %placeHolders with the values.
308
   &doPlaceholderSubstitution( $install, \%placeHolders );
101 rodolico 309
 
144 rodolico 310
   &logIt( "Exiting populateSourceDir with values\n" . Dumper( $install ) ) ;
101 rodolico 311
 
132 rodolico 312
   return 1;
313
} # populateSourceDir
314
 
315
sub GetPermission {
316
   my $install = shift;
138 rodolico 317
   &logIt( 'Entering GetPermission' );
132 rodolico 318
   print "Ready to install, please verify the following\n";
319
   print "A. Operating System:  " . $install->{'os'} . "\n";
320
   print "B. Installation Type: " . $install->{'action'} . "\n";
321
   print "C. Using Seed file: " . $install->{'configuration seed file'} . "\n" if -e $install->{'configuration seed file'};
322
   print "D. Target Binary Directory: " . $install->{'bindir'} . "\n";
323
   print "E. Target Configuration Directory: " . $install->{'confdir'} . "\n";
324
   print "F. Automatic Running: " . ( $install->{'crontab'} ? $install->{'crontab'} : 'No' ) . "\n";
325
   print "G. Install Missing Perl Libraries\n";
326
   foreach my $task ( sort keys %{ $install->{'missing libraries'} } ) {
144 rodolico 327
      print "\t$task -> " . $install->{'missing libraries'}->{$task}->{'command'} . ' ' . $install->{'missing libraries'}->{$task}->{'parameter'} . "\n";
101 rodolico 328
   }
132 rodolico 329
   print "H. Install Missing Binaries\n";
330
   foreach my $task ( sort keys %{ $install->{'missing binaries'} } ) {
144 rodolico 331
      print "\t$task -> " . $install->{'missing binaries'}->{$task}->{'command'} . ' ' . $install->{'missing binaries'}->{$task}->{'parameter'} . "\n";
132 rodolico 332
   }
333
   return &yesno( "Do you want to proceed?" );
101 rodolico 334
}
335
 
132 rodolico 336
# note, this fails badly if you stick non-numerics in the version number
337
# simply create a "number" from the version which may have an arbitrary
338
# number of digits separated by a period, for example
339
# 1.2.5
340
# while there are digits, divide current calculation by 100, then add the last
341
# digit popped of. So, 1.2.5 would become
342
# 1 + 2/100 + 5/10000, or 1.0205
343
# and 1.25.16 would become 1.2516
344
# 
345
# Will give invalid results if any set of digits is more than 99
346
sub dotVersion2Number {
347
   my $dotVersion = shift;
348
 
349
   my @t = split( '\.', $dotVersion );
350
   #print "\n$dotVersion\n" . join( "\n", @t ) . "\n";
351
   my $return = 0;
352
   while ( @t ) {
353
      $return /= 100;
354
      $return += pop @t;
355
   }
356
   #print "$return\n";
357
   return $return;
358
}
359
 
360
# there is a file named VERSIONS. We get the values out of the install
361
# directory and (if it exists) the target so we can decide what needs
362
# to be updated.
363
sub getVersions {
364
   my $install = shift;
138 rodolico 365
   &logIt( 'Entering getVersions' );
132 rodolico 366
   my $currentVersionFile = $install->{'files'}->{'VERSION'}->{'target'};
367
   my $newVersionFile = $install->{'files'}->{'VERSION'}->{'source'};
368
   if ( open FILE,"<$currentVersionFile" ) {
369
      while ( my $line = <FILE> ) {
370
         chomp $line;
371
         my ( $filename, $version, $checksum ) = split( "\t", $line );
372
         $install{'files'}->{$filename}->{'installed version'} = $version ? $version : '';
156 rodolico 373
         $install{'files'}->{$filename}->{'installed checksum'} = $checksum ? $checksum : '';
132 rodolico 374
      }
375
      close FILE;
376
   }
377
   if ( open FILE,"<$newVersionFile" ) {
378
      while ( my $line = <FILE> ) {
379
         chomp $line;
380
         my ( $filename, $version, $checksum ) = split( "\t", $line );
381
         $install->{'files'}->{$filename}->{'new version'} = $version ? $version : '';
156 rodolico 382
         $install->{'files'}->{$filename}->{'new checksum'} = $checksum ? $checksum : '';
132 rodolico 383
      }
384
      close FILE;
385
   }
386
   foreach my $file ( keys %{$$install{'files'}} ) {
156 rodolico 387
      $install{'files'}->{$file}->{'installed version'} = '' unless defined $install->{'files'}->{$file}->{'installed version'};
388
      $install{'files'}->{$file}->{'new version'} = '' unless defined $install->{'files'}->{$file}->{'new version'};
132 rodolico 389
   }
390
   return 1;
391
} # getVersions
392
 
144 rodolico 393
# checks if a directory exists and, if not, creates it
394
my %directories; # holds list of directories already created so no need to do an I/O
132 rodolico 395
 
144 rodolico 396
sub checkDirectoryExists {
397
   my ( $filename,$mod,$owner ) = @_;
398
   $mod = "0700" unless $mod;
399
   $owner = "root:root" unless $owner;
400
   &logIt( "Checking Directory for $filename with $mod and $owner" );
401
   my ($fn, $dirname) = fileparse( $filename );
402
   logIt( "\tParsing out $dirname and $filename" );
403
   return '' if exists $directories{$dirname};
404
   if ( -d $dirname ) {
405
      $directories{$dirname} = 1;
406
      return '';
407
   }
408
   if ( &runCommand( "mkdir -p $dirname", "chmod $mod $dirname", "chown $owner $dirname" ) ) {
409
      $directories{$dirname} = 1;
410
   }
411
   return '';   
412
}
413
 
414
# runs a system command. Also, if in testing mode, simply shows what
415
# would have been done.
416
sub runCommand {
417
   while ( my $command = shift ) {
418
      if ( $dryRun ) {
419
         print "$command\n";
420
      } else {
421
         `$command`;
422
      }
423
   }
424
   return 1;
425
} # runCommand
426
 
132 rodolico 427
# this actually does the installation, except for the configuration
428
sub doInstall {
429
   my $install = shift;
138 rodolico 430
   &logIt( 'Entering doInstall' );
132 rodolico 431
   my $fileList = $install->{'files'};
432
 
433
   &checkDirectoryExists( $install->{'bindir'} . '/', $install->{'default permission'}, $install->{'default owner'} . ':' . $install->{'default group'} );
434
   foreach my $file ( keys %$fileList ) {
435
      next unless ( $fileList->{$file}->{'type'} && $fileList->{$file}->{'type'} eq 'file' );
436
 
156 rodolico 437
#   *********** Removed error checking to get this working; should reenable later
438
#      if ( version->parse( $fileList->{$file}->{'installed version'} ) && version->parse( $fileList->{$file}->{'installed version'} ) < version->parse( $fileList->{$file}->{'new version'} ) ) {
439
#         # we have a new version, so overwrite it
440
#      } elsif ( $fileList->{$file}->{'installed checksum'} eq $fileList->{$file}->{'installed checksum'} ) { # has file been modified
441
#      }
442
#         
443
#
444
#      next if $install->{'action'} eq 'upgrade' && ! defined( $fileList->{$file}->{'installed version'} )
445
#              ||
446
#              ( &dotVersion2Number( $fileList->{$file}->{'new version'} ) <= &dotVersion2Number($fileList->{$file}->{'installed version'} ) );
208 rodolico 447
      # check the directory and permissions, creating directory and setting permissions if necessary
132 rodolico 448
      &checkDirectoryExists( $fileList->{$file}->{'target'}, $install->{'default permission'}, $install->{'default owner'} . ':' . $install->{'default group'} );
208 rodolico 449
      # copy the files to the new directory
211 rodolico 450
      &runCommand( "cp $fileList->{$file}->{'source'} $fileList->{$file}->{'target'}" ) unless $fileList->{$file}->{'source'} eq $fileList->{$file}->{'target'};
451
      &runCommand( "chmod $fileList->{$file}->{'permission'} $fileList->{$file}->{'target'}",
452
                   "chown $fileList->{$file}->{'owner'} $fileList->{$file}->{'target'}"
453
                 ) if -e $fileList->{$file}->{'target'};
132 rodolico 454
      # if there is a post action, run it and store any return in @feedback
455
      push @feedback, `$fileList->{$file}->{'post action'}` if defined $fileList->{$file}->{'post action'};
456
      # if there is a message to be passed, store it in @messages
156 rodolico 457
      push @messages, $fileList->{$file}->{'message'} if defined $fileList->{$file}->{'message'};
132 rodolico 458
   } # foreach file
459
   return 1;
460
}
461
 
462
 
463
# installs binaries and libraries
464
sub installOSStuff {
465
   my $install = shift;
144 rodolico 466
   my %commands;
132 rodolico 467
   my @actions = values( %{ $install->{'missing libraries'} } );
468
   push @actions, values( %{ $install->{'missing binaries'} } );
469
   foreach my $action ( @actions ) {
144 rodolico 470
      $commands{$action->{'command'}} .= ' ' . $action->{'parameter'};
211 rodolico 471
      #&logIt( $action );
472
      #&runCommand( $action );
132 rodolico 473
   }
144 rodolico 474
   foreach my $command ( keys %commands ) {
208 rodolico 475
      &logIt( $command );
476
      print "Running command $command $commands{$command}\n" unless $quiet;
144 rodolico 477
      `$command $commands{$command}`;
478
   }
132 rodolico 479
}
144 rodolico 480
 
481
################################################################
482
# validateCPAN
483
#
484
# some of the systems will need to run cpan to get some perl modules.
485
# this will go through each of them and see if command starts with cpan
486
# and, if so, will check that cpan is installed and configured for root.
487
#
488
# when cpan is installed, it requires one manual run as root from the cli
489
# to determine where to get the files. If that is not done, cpan can not
490
# be controlled by a program. We check to see if cpan is installed, then
491
# verify /root/.cpan has been created by the configuration tool
492
################################################################
493
 
494
 
495
sub validateCPAN {
496
   my $libraries = shift;
497
   my $needCPAN = 0;
498
   foreach my $app ( keys %$libraries ) {
499
      if ( $libraries->{$app}->{'command'} =~ m/^cpan/ ) {
500
         $needCPAN = 1;
501
         last;
502
      }
503
   }
504
   return unless $needCPAN;
505
   if ( `which cpan` ) {
506
      die "****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';
507
   } else {
508
      die 'In order to install on this OS, we need cpan, which should have been installed with perl.' .
509
          " Can not continue until cpan is installed and configured\n";
510
   }
208 rodolico 511
}
512
 
513
# set up the config file.
514
# at worst, we'll have an empty configuration file
515
sub checkConfig {
516
   my $install = shift;
517
   # if the configuration file does not exist, create one
518
   if ( not -e $install->{'configuration'}->{'configuration file'} ) {
519
      &logIt( "Configuration file " . $install->{'configuration'}->{'configuration file'} . " does not exist, creating" );
520
      &checkDirectoryExists(
521
            $install->{'configuration'}->{'configuration file'},
522
            $install->{'configuration'}->{'permission'},
523
            $install->{'configuration'}->{'owner'}
524
            );
525
      if ( -e $install->{'configuration seed file'} ) {
526
         &logIt( "Seed file " . $install->{'configuration seed file'} . " exists, using as default" );
527
         copy( $install->{'configuration seed file'}, $install->{'configuration'}->{'configuration file'} );
528
      } else { # we don't have a seed, and we don't have a configuration file, so just give it an empty one
529
         &logIt( "No seed file or configuration file, creating an empty YAML" );
530
         open YAML, '>' . $install->{'configuration'}->{'configuration file'} 
531
            or die "Could not create configuration file " . $install->{'configuration'}->{'configuration file'} . ": $!\n";
532
         print YAML "# This is an empty configuration file\n---\n";
533
         close YAML;
534
      }
535
   }
536
}
537
 
538
# create a cron entry if necessary
539
sub cronTab {
540
   my $install = shift;
541
   # set up crontab, if necessary
542
   &logIt("Setting up crontab as " . $install->{'crontab'} );
543
   &runCommand( $install->{'crontab'} ) if defined ( $install->{'crontab'} );
144 rodolico 544
}   
211 rodolico 545
 
132 rodolico 546
 
547
################################################################
548
#               Main Code                                      #
549
################################################################
550
 
551
# handle any command line parameters that may have been passed in
552
 
553
GetOptions (
554
            "os|o=s"      => \$os,      # pass in the operating system
555
            "dryrun|n"    => \$dryRun,  # do NOT actually do anything
556
            'help|h'      => \$help,
206 rodolico 557
            'version|v'   => \$version,
211 rodolico 558
            'quiet|q'     => \$quiet
132 rodolico 559
            ) or die "Error parsing command line\n";
560
 
561
if ( $help ) { &help() ; exit; }
156 rodolico 562
if ( $version ) { use File::Basename; print basename($0) . " $VERSION\n"; exit; }
132 rodolico 563
 
211 rodolico 564
 
156 rodolico 565
print "Logging to $logFile\n";
211 rodolico 566
 
138 rodolico 567
&logIt( 'Beginning installation' );
568
 
208 rodolico 569
# determine the operating system and set up installer hash with correct values
211 rodolico 570
$install{'os'} = &setUpOperatingSystemSpecific( \%install, \%operatingSystems, $os ? $os : `$installerDir/determineOS`, $sourceDir );
138 rodolico 571
&logIt( "Operating System is $install{'os'}" );
572
 
208 rodolico 573
# check libraries necessary are loaded, and if not, track the ones we need
132 rodolico 574
$install{'missing libraries'} = &validateLibraries( \%libraries, $install{'os'} );
144 rodolico 575
&logIt( "Missing Libraries\n" . Dumper( $install{'missing libraries'} ) );
138 rodolico 576
 
208 rodolico 577
# Check that required binaries are installed and create list of the ones we need
132 rodolico 578
$install{'missing binaries'} = &validateBinaries( \%binaries, $install{'os'} );
144 rodolico 579
&logIt( "Missing binaries\n" . Dumper( $install{'missing binaries'} ) );
138 rodolico 580
 
208 rodolico 581
# if we need libraries and the os needs to use CPAN, validate CPAN
582
&validateCPAN( $install{'missing libraries'} ) if ( $install{'missing libraries'} );
144 rodolico 583
 
208 rodolico 584
# determine if it is an upgrade or fresh install and default to creating conf and cron
132 rodolico 585
&getInstallActions( \%install );
144 rodolico 586
&logIt( "Completed getInstallActions\n" .  Dumper( \%install ) );
138 rodolico 587
 
208 rodolico 588
# go through %install and replace all variables with correct values
589
# moving directories as needed in the %install
590
&massageInstallValues( \%install, $sourceDir );
132 rodolico 591
 
208 rodolico 592
#print Dumper( \%install ) ; die;
593
 
594
# ask permission if $quiet not set
206 rodolico 595
if ( $quiet || &GetPermission( \%install ) ) {
208 rodolico 596
   # install binaries and libraries as needed
132 rodolico 597
   &installOSStuff( \%install );
208 rodolico 598
   # do a version comparison unless we already have it in place, or it is a new install
211 rodolico 599
   &getVersions( \%install );
208 rodolico 600
   # move the binaries in place unless they are already there
211 rodolico 601
   &doInstall( \%install );
132 rodolico 602
} else {
603
   die "Please fix whatever needs to be done and try again\n";
138 rodolico 604
   &logIt( "User chose to kill process" );
132 rodolico 605
}
606
 
210 rodolico 607
# hack to set permissions.
608
`chown root:root $install{bindir}`;
609
`chmod 700 $install{bindir}`;
610
 
208 rodolico 611
# set up automatic running
612
&cronTab( \%install );
613
# make sure something is in the configuration file
614
&checkConfig( \%install );
615
 
144 rodolico 616
&logIt( "Installation done, running \&postInstall if it exists" );
132 rodolico 617
 
211 rodolico 618
my $configCommand = &postInstall( \%install, $quiet ) if defined( &postInstall );
619
print "$configCommand\n";
144 rodolico 620
 
621
1;