Subversion Repositories camp_sysinfo_client_3

Rev

Rev 34 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 34 Rev 35
Line 12... Line 12...
12
   use lib File::Spec->catdir($FindBin::Bin);
12
   use lib File::Spec->catdir($FindBin::Bin);
13
}
13
}
14
 
14
 
15
use sysinfoconf;
15
use sysinfoconf;
16
use File::Basename;
16
use File::Basename;
-
 
17
use Getopt::Long;
-
 
18
Getopt::Long::Configure ("bundling"); # allow -vd --os='debian'
17
 
19
 
18
use Data::Dumper;
20
use Data::Dumper;
19
 
21
 
20
# $TESTING can have the following values
22
# $verbose can have the following values
21
# 0 - do everything
23
# 0 - do everything
22
# 1 - Do everything except the install, display what would be done
24
# 1 - Do everything except the install, display what would be done
23
# 2 - Be verbose to STDERR
25
# 2 - Be verbose to STDERR
24
# 3 - Be very verbose
26
# 3 - Be very verbose
25
my $TESTING = 1; # if test mode, simply show what would be done
27
my $verbose = 0; # if test mode, simply show what would be done
-
 
28
my $dryRun = 0;
-
 
29
my $os;
-
 
30
my $help = 0;
-
 
31
my $version = 0;
26
 
32
 
27
my $status; # exit status of the processes
33
my $status; # exit status of the processes
28
my $sourceDir = File::Spec->catdir($FindBin::Bin);
34
my $sourceDir = File::Spec->catdir($FindBin::Bin);
29
my $installType;
35
my $installType;
30
 
36
 
31
my %install = (  'bindir' => '/opt/camp/sysinfo-client',
37
my %install = (  'bindir' => '/opt/camp/sysinfo-client',
32
                 'confdir' => '/etc/camp/sysinfo-client',
38
                 'confdir' => '/etc/camp/sysinfo-client',
33
                 'application name' => 'sysinfo client',
39
                 'application name' => 'sysinfo client',
-
 
40
                 'configuration' => {
-
 
41
                          'configurator' => '<bindir>/configure.pl',
-
 
42
                          'configuration file' => '<confdir>/sysinfo-client.conf',
-
 
43
                          'configuration seed file' => 'sysinfo-client.seed',
-
 
44
                          'permission' => '700',
-
 
45
                          'owner'      => 'root',
-
 
46
                          'target'     => '<confdir>'
-
 
47
                            },
34
                 'files' => {
48
                 'files' => {
35
                           'configure.pl' => { 
49
                           'configure.pl' => { 
36
                                 'type' => 'file',
50
                                 'type' => 'file',
37
                                 'permission' => '700', 
51
                                 'permission' => '700', 
38
                                 'owner' => 'root:root', 
52
                                 'owner' => 'root:root', 
Line 128... Line 142...
128
                                 'permission' => '700', 
142
                                 'permission' => '700', 
129
                                 'owner' => 'root:root', 
143
                                 'owner' => 'root:root', 
130
                                 'target' =>  '<bindir>',
144
                                 'target' =>  '<bindir>',
131
                                 'action' => 'chmod 700 *'
145
                                 'action' => 'chmod 700 *'
132
                              },
146
                              },
133
                              'sysinfo-client.conf' => {
-
 
134
                                 'type' => 'file',
-
 
135
                                 'create' => '<bindir>/configure.pl',
-
 
136
                                 'permission' => '700',
-
 
137
                                 'owner'      => 'root',
-
 
138
                                 'target'     => '<confdir>'
-
 
139
                              }
-
 
140
                     }
147
                     }
141
                  );
148
                  );
142
 
149
 
143
# hash to set up os specific rules                  
150
# hash to set up os specific rules                  
144
my %operatingSystems = (
151
my %operatingSystems = (
145
                  'debian' => {
152
                  'debian' => {
146
                     'bindir' => '/opt/camp/sysinfo-client',
153
                     'bindir' => '/opt/camp/sysinfo-client',
147
                     'confdir' => '/etc/camp/sysinfo-client',
154
                     'confdir' => '/etc/camp/sysinfo-client',
148
                     'crontab' => '/etc/cron.daily/sysinfo-client',
155
                     'crontab' => 'ln -s <bindir>/sysinfo-client /etc/cron.daily/sysinfo-client',
149
                     'modules' => '/^((dpkg)|(unix)|(ipmi))/',
156
                     'modules' => '/^((dpkg)|(unix)|(ipmi))/',
150
                  },
157
                  },
151
                  'ipfire' => {
158
                  'ipfire' => {
152
                     'bindir' => '/opt/camp/sysinfo-client',
159
                     'bindir' => '/opt/camp/sysinfo-client',
153
                     'confdir' => '/etc/camp/sysinfo-client',
160
                     'confdir' => '/etc/camp/sysinfo-client',
154
                     'crontab' => '/etc/fcron.daily/sysinfo-client.fcron',
161
                     'crontab' => 'ln -s <bindir>sysinfo-client /etc/fcron.daily/sysinfo-client.fcron',
155
                     'modules' => '/^((ipfire)|(unix))/',
162
                     'modules' => '/^((ipfire)|(unix))/',
156
                  }
163
                  }
157
                  );
164
                  );
158
                  
165
                  
159
 
166
 
160
# attempt to locate the operating system.
167
# attempt to locate the operating system.
161
# if found, will set some defaults for it.
168
# if found, will set some defaults for it.
162
sub getOS {
169
sub getOS {
163
   my ( $install, $operatingSystems ) = @_;
170
   my ( $install, $operatingSystems, $os ) = @_;
-
 
171
   if ( ! $os ) { # we don't know, so we must try to figure it out
164
   my $osString = `uname -a`;
172
      my $osString = `uname -a`;
165
   foreach my $osType ( keys %$operatingSystems ) {
173
      foreach my $osType ( keys %$operatingSystems ) {
166
      print "Checking if OS is $osType in $osString\n" if $TESTING > 2;
174
         print "Checking if OS is $osType in $osString\n" if $verbose > 2;
167
      next unless $osString =~ m/$osType/i;
175
         next unless $osString =~ m/$osType/i;
168
      print "Yes, it is $osType\n" if $TESTING > 2;
176
         print "Yes, it is $osType\n" if $verbose > 2;
169
      # We found the OS, set up some defaults
177
         # We found the OS, set up some defaults
170
      $$install{'os'} = $osType;
178
         $os = $osType;
171
      print "Setting keys for operating system\n" if $TESTING > 2;
-
 
172
      for my $key ( keys $$operatingSystems{ $osType } ) {
-
 
173
         $$install{$key} = $operatingSystems{ $osType }{$key};
-
 
174
      } # if it is a known OS
-
 
175
      return 1;
179
      } # foreach
176
   }
180
   }
-
 
181
   if ( $os ) {
-
 
182
      $$install{'os'} = $os;
-
 
183
      print "Setting keys for operating system\n" if $verbose > 2;
-
 
184
      foreach my $key ( keys $$operatingSystems{ $os } ) {
-
 
185
         $$install{$key} = $operatingSystems{ $os }{$key};
-
 
186
      } # if it is a known OS
-
 
187
   } # if
177
   return 0;
188
   return $os;
178
} # getOperatingSystem
189
} # getOperatingSystem
179
 
190
 
180
# get some input from the user and decide how to install/upgrade/remove/whatever
191
# get some input from the user and decide how to install/upgrade/remove/whatever
181
sub getInstallActions {
192
sub getInstallActions {
182
   my $install = shift;
193
   my $install = shift;
183
   if ( ! &yesno( "This looks like a $$install{'os'} machine, correct?" ) ) {
194
   if ( ! &yesno( "This looks like a $$install{'os'} machine, correct?" ) ) {
184
      die "User Aborted\n" if &yesno( "If we continue, I will set this up like a $$install{'os'} system. Abort?" );
195
      die "User Aborted\n" if &yesno( "If we continue, I will set this up like a $$install{'os'} system. Abort?" );
185
         
-
 
186
   }
196
   }
187
   if ( -d $$install{'confdir'} ) {
197
   if ( -d $$install{'confdir'} ) {
188
      $$install{'action'} = &getAnswer( "It looks like $$install{'application name'} is already installed, what do you want to do?", 
198
      $$install{'action'} = &getAnswer( "It looks like $$install{'application name'} is already installed, what do you want to do?", 
189
                            ( "upgrade","remove", "overwrite" )
199
                            ( "upgrade","remove", "overwrite" )
190
                          );
200
                          );
Line 196... Line 206...
196
         die "Can not continue at this time: Do not understand your system\n";
206
         die "Can not continue at this time: Do not understand your system\n";
197
      }
207
      }
198
   }
208
   }
199
   $$install{'build config'} = &yesno( "Edit config file when done?" );
209
   $$install{'build config'} = &yesno( "Edit config file when done?" );
200
   $$install{'setup cron'} = &yesno( "Set up for automatic running via crontab?" );
210
   $$install{'setup cron'} = &yesno( "Set up for automatic running via crontab?" );
201
   &showWork( $install );
-
 
202
   die unless &yesno( "Ready to run? Select No to abort." );
-
 
203
}
211
}
204
 
212
 
205
sub showWork { 
213
sub showWork { 
206
   my $install = shift;
214
   my $install = shift;
207
   print Dumper( \%install );
215
   print Dumper( \%install );
208
}
216
}
-
 
217
 
-
 
218
 
-
 
219
sub doPlaceholderSubstitution {
-
 
220
   my ($hash, $placeholder) = @_;
-
 
221
   return if ref $hash ne 'HASH';
-
 
222
   foreach my $key ( keys %$hash ) {
-
 
223
      if ( ref( $$hash{$key} ) ) {
-
 
224
         &doPlaceholderSubstitution( $$hash{$key}, $placeholder );
-
 
225
      } else {
-
 
226
         foreach my $place ( keys %$placeholder ) {
-
 
227
            $$hash{$key} =~ s/$place/$$placeholder{$place}/;
-
 
228
         } # foreach
-
 
229
      } # if..else
-
 
230
   } # foreach
-
 
231
   return;
-
 
232
}
209
   
233
   
210
# This will go through and first, see if anything is a directory, in
234
# This will go through and first, see if anything is a directory, in
211
# which case, we'll create new entries for all files in there.
235
# which case, we'll create new entries for all files in there.
212
# then, it will do keyword substitution of <bindir> and <confdir>
236
# then, it will do keyword substitution of <bindir> and <confdir>
213
# to populate the target.
237
# to populate the target.
214
# When this is done, each file should have a source and target that is
238
# When this is done, each file should have a source and target that is
215
# a fully qualified path and filename
239
# a fully qualified path and filename
216
sub populateSourceDir {
240
sub populateSourceDir {
217
   my ( $install, $sourceDir ) = @_;
241
   my ( $install, $sourceDir ) = @_;
-
 
242
   my %placeHolders = 
-
 
243
      ( 
218
   my $bindir = $$install{'bindir'};
244
        '<bindir>' => $$install{'bindir'},
219
   my $confdir = $$install{'confdir'};
245
        '<confdir>' => $$install{'confdir'}
-
 
246
      );
220
 
247
 
221
   my $allFiles = $$install{'files'};
248
   my $allFiles = $$install{'files'};
222
 
249
 
-
 
250
   # find all directory entries and load files in that directory into $$install{'files'}
223
   foreach my $dir ( keys %$allFiles ) {
251
   foreach my $dir ( keys %$allFiles ) {
224
      if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
252
      if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
225
         print "Found directory $dir\n" if $TESTING > 2;
253
         print "Found directory $dir\n" if $verbose > 2;
226
         if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
254
         if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
227
            my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
255
            my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
228
            print "\tFound files " . join( ' ', @files ) . "\n" if $TESTING > 2;
256
            print "\tFound files " . join( ' ', @files ) . "\n" if $verbose > 2;
229
            foreach my $file ( @files ) {
257
            foreach my $file ( @files ) {
230
               $$allFiles{ $file }{'type'} = 'file';
258
               $$allFiles{ $file }{'type'} = 'file';
231
               $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
259
               $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
232
               $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
260
               $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
233
               $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
261
               $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
234
            } # foreach
262
            } # foreach
235
            closedir $dh;
263
            closedir $dh;
236
         } # if opendir
264
         } # if opendir
237
      } # if it is a directory
265
      } # if it is a directory
238
   } # foreach
266
   } # foreach
-
 
267
 
239
   print Dumper( $install ) if $TESTING > 2;
268
   # find all files, and set the source directory, and add the filename to
-
 
269
   # the target
240
   foreach my $file ( keys %$allFiles ) {
270
   foreach my $file ( keys %$allFiles ) {
241
      print STDERR "$file\t$bindir\t$$allFiles{$file}{'target'}\n" if $TESTING > 1;
-
 
242
      $$allFiles{$file}{'source'} = "$sourceDir/$file";
271
      $$allFiles{$file}{'source'} = "$sourceDir/$file";
243
      $$allFiles{$file}{'target'} =~ s/<bindir>/$bindir/gi;
-
 
244
      $$allFiles{$file}{'target'} =~ s/<confdir>/$confdir/gi;
-
 
245
      $$allFiles{$file}{'target'} .= "/$file";
272
      $$allFiles{$file}{'target'} .= "/$file";
246
      if ( $$allFiles{$file}{'create'} ) {
-
 
247
         $$allFiles{$file}{'create'} =~ s/<bindir>/$bindir/gi;
-
 
248
         $$allFiles{$file}{'create'} =~ s/<confdir>/$confdir/gi;
-
 
249
         $$allFiles{$file}{'create'} .= "/file";
-
 
250
      }
-
 
251
      
-
 
252
   } # foreach
273
   } # foreach
-
 
274
 
-
 
275
   # finally, do place holder substitution. This recursively replaces all keys
-
 
276
   # in  %placeHolders with the values.
-
 
277
   &doPlaceholderSubstitution( $install, \%placeHolders );
-
 
278
 
-
 
279
   print Dumper( $install ) if $verbose > 2;
253
   
280
 
254
   return 1;
281
   return 1;
255
} # populateSourceDir
282
} # populateSourceDir
256
 
283
 
257
# there is a file named VERSIONS. We get the values out of the install
284
# there is a file named VERSIONS. We get the values out of the install
258
# directory and (if it exists) the target so we can decide what needs
285
# directory and (if it exists) the target so we can decide what needs
Line 264... Line 291...
264
   if ( open FILE,"<$currentVersionFile" ) {
291
   if ( open FILE,"<$currentVersionFile" ) {
265
      while ( my $line = <FILE> ) {
292
      while ( my $line = <FILE> ) {
266
         chomp $line;
293
         chomp $line;
267
         my ( $filename, $version, $checksum ) = split( "\t", $line );
294
         my ( $filename, $version, $checksum ) = split( "\t", $line );
268
         $$install{'files'}{$filename}{'installed version'} = $version ? $version : '';
295
         $$install{'files'}{$filename}{'installed version'} = $version ? $version : '';
269
#         $$install{'files'}{$filename}{'installed checksum'} = $checksum ? $checksum : '';
-
 
270
      }
296
      }
271
      close FILE;
297
      close FILE;
272
   }
298
   }
273
   if ( open FILE,"<$newVersionFile" ) {
299
   if ( open FILE,"<$newVersionFile" ) {
274
      while ( my $line = <FILE> ) {
300
      while ( my $line = <FILE> ) {
275
         chomp $line;
301
         chomp $line;
276
         my ( $filename, $version, $checksum ) = split( "\t", $line );
302
         my ( $filename, $version, $checksum ) = split( "\t", $line );
277
         $$install{'files'}{$filename}{'new version'} = $version ? $version : '';
303
         $$install{'files'}{$filename}{'new version'} = $version ? $version : '';
278
#         $$install{'files'}{$filename}{'new checksum'} = $checksum ? $checksum : '';
-
 
279
      }
304
      }
280
      close FILE;
305
      close FILE;
281
   }
306
   }
282
   return 1;
307
   return 1;
283
} # getVersions
308
} # getVersions
284
 
309
 
285
# runs a system command. Also, if in testing mode, simply shows what
-
 
286
# would have been done.
-
 
287
sub runCommand {
-
 
288
   while ( my $command = shift ) {
-
 
289
      if ( $TESTING ) {
-
 
290
         print "$command\n";
-
 
291
      } else {
-
 
292
         `$command`;
-
 
293
      }
-
 
294
   }
-
 
295
   return 1;
-
 
296
} # runCommand
-
 
297
 
-
 
298
# checks if a directory exists and, if not, creates it
-
 
299
my %directories; # holds list of directories already created so no need to do an I/O
-
 
300
 
-
 
301
sub checkDirectoryExists {
-
 
302
   my ( $filename,$mod,$owner ) = @_;
-
 
303
   $mod = "0700" unless $mod;
-
 
304
   $owner = "root:root" unless $owner;
-
 
305
   print "Checking Directory for $filename with $mod and $owner\n" if $TESTING > 2;
-
 
306
   my ($fn, $dirname) = fileparse( $filename );
-
 
307
   print "\tParsing out $dirname and $filename\n" if $TESTING > 2;
-
 
308
   return '' if exists $directories{$dirname};
-
 
309
   if ( -d $dirname ) {
-
 
310
      $directories{$dirname} = 1;
-
 
311
      return '';
-
 
312
   }
-
 
313
   if ( &runCommand( "mkdir -p $dirname", "chmod $mod $dirname", "chown $owner $dirname" ) ) {
-
 
314
      $directories{$dirname} = 1;
-
 
315
   }
-
 
316
   return '';   
-
 
317
}
-
 
318
   
-
 
319
# this actually does the installation, except for the configuration
310
# this actually does the installation, except for the configuration
320
sub doInstall {
311
sub doInstall {
321
   my $install = shift;
312
   my $install = shift;
322
   my $fileList = $$install{'files'};
313
   my $fileList = $$install{'files'};
323
   
314
   
Line 335... Line 326...
335
            );
326
            );
336
   } # foreach file
327
   } # foreach file
337
   return 1;
328
   return 1;
338
}
329
}
339
 
330
 
-
 
331
sub postInstall {
-
 
332
   my $install = shift;
340
# parse the flags to decide the actions:
333
   # set up crontab, if necessary
-
 
334
   # run configurator, if needed
-
 
335
   my %config;
-
 
336
   my $seedFile = $install{'configuration'}{'configuration seed file'};
-
 
337
   my $confFile = $install{'configuration'}{'configuration file'};
-
 
338
   my $content;
341
# install - assumes is a new install, overwrites everything
339
   if ( -f $seedFile  && &yesno( 'Add installation seed file? ' ) ) {
-
 
340
      my $clientName;
-
 
341
      my $serialNumber;
-
 
342
      my $hostname;
-
 
343
      my @moduleDirs;
-
 
344
      my @scriptDirs;
-
 
345
      my $transports = {};
-
 
346
         
342
# upgrade - Checks for new files and overwrites only them
347
      print "Loading seed file $seedFile\n";
-
 
348
      open SEED, "<$seedFile" or die "Could not open $seedFile: $!\n";
343
# uninstall - Removes everything
349
      $content = join( '', <SEED> );
-
 
350
      close SEED;
344
# reinstall - overwrites everything with fresh copy
351
      # now, eval the information we just read.
-
 
352
      # NOTE: we must turn off strict while doing this, and we die if something breaks.
-
 
353
      no strict "vars"; eval( $content ); use strict "vars"; die "Error during eval: $@\n" if $@;
345
 
354
 
-
 
355
      if (  -f $confFile  ) {
-
 
356
         print "Loading configuration file $confFile\n";
-
 
357
         open SEED, "<$confFile" or die "Could not open $confFile: $!\n";
-
 
358
         $content = join( '', <SEED> );
346
################
359
         close SEED;
347
# check for the configuration file!!!
360
         # now, eval the information we just read.
-
 
361
         # NOTE: we must turn off strict while doing this, and we die if something breaks.
-
 
362
         no strict "vars"; eval( $content ); use strict "vars"; die "Error during eval: $@\n" if $@;
-
 
363
      }
-
 
364
      $config{'clientName'} = $clientName;
-
 
365
      $config{'serialNumber'} = $serialNumber;
-
 
366
      $config{'hostname'} = $hostname;
-
 
367
      $config{'moduleDirs'} = [ @moduleDirs ];
-
 
368
      $config{'scriptDirs'} = [ @scriptDirs ];
-
 
369
      $config{'transports'} = $transports;
-
 
370
 
-
 
371
      $content = &showConf( \%config );
348
################
372
      print $content;
-
 
373
      print &writeConfig( $install{'configuration'}{'configuration file'} , $content ) . "\n"
-
 
374
         if ( &yesno( "Write the above configuration to $install{'configuration'}{'configuration file'}?" ) );
-
 
375
   }
-
 
376
   
-
 
377
   if ( ( -x $install{'configuration'}{'configurator'} ) && $install{'build config'} ) {
-
 
378
      exec( $install{'configuration'}{'configurator'} );
-
 
379
   }
-
 
380
}
349
 
381
 
-
 
382
sub help {
-
 
383
   my $oses = join( ' ', keys %operatingSystems );
-
 
384
   print <<END
-
 
385
$0 --verbose=x --os="osname" --dryrun --help --version
-
 
386
 
-
 
387
--os      - osname is one of [$oses]
-
 
388
--dryrun  - do not actually do anything, just tell you what I'd do
-
 
389
--verbose - x is 0 (normal) to 3 (horrible)
-
 
390
END
-
 
391
}
350
 
392
 
351
 
393
 
352
 
394
 
-
 
395
##########################################
-
 
396
# Main Loop
-
 
397
##########################################
-
 
398
 
-
 
399
# handle any command line parameters that may have been passed in
-
 
400
 
-
 
401
GetOptions (
-
 
402
            "verbose|v=i" => \$verbose, # verbosity level, 0-9
-
 
403
            "os|o=s"      => \$os,      # pass in the operating system
-
 
404
            "dryrun|n"    => \$dryRun,  # do NOT actually do anything
-
 
405
            'help|h'      => \$help,
-
 
406
            'version|V'   => \$version
-
 
407
            ) or die "Error parsing command line\n";
-
 
408
                  
-
 
409
if ( $help ) { &help() ; exit; }
-
 
410
if ( $version ) { print "$0 version $VERSION\n"; exit; }
-
 
411
&setDryRun( $dryRun ); # tell the library whether this is a dry run or not
-
 
412
 
353
# figure out if we know our operating system
413
# figure out if we know our operating system
354
$status = &getOS( \%install, \%operatingSystems );
414
$os = &getOS( \%install, \%operatingSystems, $os );
355
 
415
 
356
$installType = getInstallActions( \%install );
416
$installType = &getInstallActions( \%install );
357
 
417
 
358
# based on the defaults, flesh out the install hash
418
# based on the defaults, flesh out the install hash
359
$status = &populateSourceDir( \%install, $sourceDir );
419
$status = &populateSourceDir( \%install, $sourceDir );
360
 
420
 
-
 
421
 
361
$status = &getVersions( \%install );
422
$status = &getVersions( \%install );
362
 
423
 
-
 
424
&showWork( \%install );
-
 
425
die unless &yesno( "Ready to run? Select No to abort." );
-
 
426
 
363
$status = &doInstall( \%install );
427
$status = &doInstall( \%install );
364
 
428
 
-
 
429
$status = &postInstall( \%install );
365
 
430
 
366
print Dumper( \%install ) if $TESTING > 2;
431
1;