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