Subversion Repositories camp_sysinfo_client_3

Rev

Rev 33 | Blame | Last modification | View Log | RSS feed

#! /usr/bin/env perl

use strict;
use warnings;

our $VERSION = '1.1.3';

# find our location and use it for searching for libraries
BEGIN {
   use FindBin;
   use File::Spec;
   use lib File::Spec->catdir($FindBin::Bin);
}

use sysinfoconf;
use File::Basename;

use Data::Dumper;

# $TESTING can have the following values
# 0 - do everything
# 1 - Do everything except the install, display what would be done
# 2 - Be verbose to STDERR
# 3 - Be very verbose
my $TESTING = 1; # if test mode, simply show what would be done

my $status; # exit status of the processes
my $sourceDir = File::Spec->catdir($FindBin::Bin);
my $installType;

my %install = (  'bindir' => '/opt/camp/sysinfo-client',
                 'confdir' => '/etc/camp/sysinfo-client',
                 'application name' => 'sysinfo client',
                 'files' => {
                           'configure.pl' => { 
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>'
                              },
                           'sysinfo-client' => { 
                                 'type' => 'file',
                                 'permission' => '700',
                                 'owner' => 'root:root',
                                 'target' =>  '<bindir>'
                              },
                           'sysinfoconf.pm' => {
                                 'type' => 'file',
                                 'permission' => '600',
                                 'owner' => 'root:root',
                                 'target' =>  '<bindir>'
                              },
                           'debian.pm' => {
                                 'type' => 'file',
                                 'permission' => '600',
                                 'owner' => 'root:root',
                                 'target' =>  '<bindir>' 
                              },
                           'ipfire.pm' => { 
                                 'type' => 'file',
                                 'permission' => '600',
                                 'owner' => 'root:root',
                                 'target' =>  '<bindir>'
                              },
                           'notes' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>'
                              },
                           'sysinfo-client.conf.template' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'uninstall.pl' => { 
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'getSendEmail.pl' => { 
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'upgrade.pl' => { 
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'install.pl' => {
                                 'type' => 'file',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'MANIFEST' => {
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'sysinfo-client.seed.example' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                           'VERSION' => { 
                                 'type' => 'file',
                                 'permission' => '600', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>' 
                              },
                              'modules' => {
                                 'type' => 'directory',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>',
                                 'action' => 'chmod 700 *'
                              },
                              'scripts' => {
                                 'type' => 'directory',
                                 'permission' => '700', 
                                 'owner' => 'root:root', 
                                 'target' =>  '<bindir>',
                                 'action' => 'chmod 700 *'
                              },
                              'sysinfo-client.conf' => {
                                 'type' => 'file',
                                 'create' => '<bindir>/configure.pl',
                                 'permission' => '700',
                                 'owner'      => 'root',
                                 'target'     => '<confdir>'
                              }
                     }
                  );

# hash to set up os specific rules                  
my %operatingSystems = (
                  'debian' => {
                     'bindir' => '/opt/camp/sysinfo-client',
                     'confdir' => '/etc/camp/sysinfo-client',
                     'crontab' => '/etc/cron.daily/sysinfo-client',
                     'modules' => '/^((dpkg)|(unix)|(ipmi))/',
                  },
                  'ipfire' => {
                     'bindir' => '/opt/camp/sysinfo-client',
                     'confdir' => '/etc/camp/sysinfo-client',
                     'crontab' => '/etc/fcron.daily/sysinfo-client.fcron',
                     'modules' => '/^((ipfire)|(unix))/',
                  }
                  );
                  

# attempt to locate the operating system.
# if found, will set some defaults for it.
sub getOS {
   my ( $install, $operatingSystems ) = @_;
   my $osString = `uname -a`;
   foreach my $osType ( keys %$operatingSystems ) {
      print "Checking if OS is $osType in $osString\n" if $TESTING > 2;
      next unless $osString =~ m/$osType/i;
      print "Yes, it is $osType\n" if $TESTING > 2;
      # We found the OS, set up some defaults
      $$install{'os'} = $osType;
      print "Setting keys for operating system\n" if $TESTING > 2;
      for my $key ( keys $$operatingSystems{ $osType } ) {
         $$install{$key} = $operatingSystems{ $osType }{$key};
      } # if it is a known OS
      return 1;
   }
   return 0;
} # getOperatingSystem

# get some input from the user and decide how to install/upgrade/remove/whatever
sub getInstallActions {
   my $install = shift;
   if ( ! &yesno( "This looks like a $$install{'os'} machine, correct?" ) ) {
      die "User Aborted\n" if &yesno( "If we continue, I will set this up like a $$install{'os'} system. Abort?" );
         
   }
   if ( -d $$install{'confdir'} ) {
      $$install{'action'} = &getAnswer( "It looks like $$install{'application name'} is already installed, what do you want to do?", 
                            ( "upgrade","remove", "overwrite" )
                          );
   } else {
      if ( &yesno( "This looks like a fresh install, correct?" ) ) {
         $$install{'action'} = 'install';
         $$install{'preseed config'} = &yesno( "Preseed the configuration file?" );
      } else {
         die "Can not continue at this time: Do not understand your system\n";
      }
   }
   $$install{'build config'} = &yesno( "Edit config file when done?" );
   $$install{'setup cron'} = &yesno( "Set up for automatic running via crontab?" );
   &showWork( $install );
   die unless &yesno( "Ready to run? Select No to abort." );
}

sub showWork { 
   my $install = shift;
   print Dumper( \%install );
}
   
# This will go through and first, see if anything is a directory, in
# which case, we'll create new entries for all files in there.
# then, it will do keyword substitution of <bindir> and <confdir>
# to populate the target.
# When this is done, each file should have a source and target that is
# a fully qualified path and filename
sub populateSourceDir {
   my ( $install, $sourceDir ) = @_;
   my $bindir = $$install{'bindir'};
   my $confdir = $$install{'confdir'};

   my $allFiles = $$install{'files'};

   foreach my $dir ( keys %$allFiles ) {
      if ( defined( $$allFiles{$dir}{'type'} ) && $$allFiles{$dir}{'type'} eq 'directory' ) {
         print "Found directory $dir\n" if $TESTING > 2;
         if ( opendir( my $dh, "$sourceDir/$dir" ) ) {
            my @files = map{ $dir . '/' . $_ } grep { ! /^\./ && -f "$sourceDir/$dir/$_" } readdir( $dh );
            print "\tFound files " . join( ' ', @files ) . "\n" if $TESTING > 2;
            foreach my $file ( @files ) {
               $$allFiles{ $file }{'type'} = 'file';
               $$allFiles{ $file }{'permission'} = $$allFiles{ $dir }{'permission'};
               $$allFiles{ $file }{'owner'} = $$allFiles{ $dir }{'owner'};
               $$allFiles{ $file }{'target'} = $$allFiles{ $dir }{'target'};
            } # foreach
            closedir $dh;
         } # if opendir
      } # if it is a directory
   } # foreach
   print Dumper( $install ) if $TESTING > 2;
   foreach my $file ( keys %$allFiles ) {
      print STDERR "$file\t$bindir\t$$allFiles{$file}{'target'}\n" if $TESTING > 1;
      $$allFiles{$file}{'source'} = "$sourceDir/$file";
      $$allFiles{$file}{'target'} =~ s/<bindir>/$bindir/gi;
      $$allFiles{$file}{'target'} =~ s/<confdir>/$confdir/gi;
      $$allFiles{$file}{'target'} .= "/$file";
      if ( $$allFiles{$file}{'create'} ) {
         $$allFiles{$file}{'create'} =~ s/<bindir>/$bindir/gi;
         $$allFiles{$file}{'create'} =~ s/<confdir>/$confdir/gi;
         $$allFiles{$file}{'create'} .= "/file";
      }
      
   } # foreach
   
   return 1;
} # populateSourceDir

# there is a file named VERSIONS. We get the values out of the install
# directory and (if it exists) the target so we can decide what needs
# to be updated.
sub getVersions {
   my $install = shift;
   my $currentVersionFile = $$install{'files'}{'VERSION'}{'target'};
   my $newVersionFile = $$install{'files'}{'VERSION'}{'source'};
   if ( open FILE,"<$currentVersionFile" ) {
      while ( my $line = <FILE> ) {
         chomp $line;
         my ( $filename, $version, $checksum ) = split( "\t", $line );
         $$install{'files'}{$filename}{'installed version'} = $version ? $version : '';
#         $$install{'files'}{$filename}{'installed checksum'} = $checksum ? $checksum : '';
      }
      close FILE;
   }
   if ( open FILE,"<$newVersionFile" ) {
      while ( my $line = <FILE> ) {
         chomp $line;
         my ( $filename, $version, $checksum ) = split( "\t", $line );
         $$install{'files'}{$filename}{'new version'} = $version ? $version : '';
#         $$install{'files'}{$filename}{'new checksum'} = $checksum ? $checksum : '';
      }
      close FILE;
   }
   return 1;
} # getVersions

# runs a system command. Also, if in testing mode, simply shows what
# would have been done.
sub runCommand {
   while ( my $command = shift ) {
      if ( $TESTING ) {
         print "$command\n";
      } else {
         `$command`;
      }
   }
   return 1;
} # runCommand

# checks if a directory exists and, if not, creates it
my %directories; # holds list of directories already created so no need to do an I/O

sub checkDirectoryExists {
   my ( $filename,$mod,$owner ) = @_;
   $mod = "0700" unless $mod;
   $owner = "root:root" unless $owner;
   print "Checking Directory for $filename with $mod and $owner\n" if $TESTING > 2;
   my ($fn, $dirname) = fileparse( $filename );
   print "\tParsing out $dirname and $filename\n" if $TESTING > 2;
   return '' if exists $directories{$dirname};
   if ( -d $dirname ) {
      $directories{$dirname} = 1;
      return '';
   }
   if ( &runCommand( "mkdir -p $dirname", "chmod $mod $dirname", "chown $owner $dirname" ) ) {
      $directories{$dirname} = 1;
   }
   return '';   
}
   
# this actually does the installation, except for the configuration
sub doInstall {
   my $install = shift;
   my $fileList = $$install{'files'};
   
   &checkDirectoryExists( $$install{'bindir'} . '/' );
   foreach my $file ( keys %$fileList ) {
      next unless ( $$fileList{$file}{'type'} && $$fileList{$file}{'type'} eq 'file' );
      next if $$install{'action'} eq 'upgrade' &&
              $$fileList{$file}{'installed version'} &&
              $$fileList{$file}{'new version'} eq $$fileList{$file}{'installed version'};
      &checkDirectoryExists( $$fileList{$file}{'target'} );
      &runCommand( 
            "cp $$fileList{$file}{'source'} $$fileList{$file}{'target'}",
            "chmod $$fileList{$file}{'permission'} $$fileList{$file}{'target'}",
            "chown  $$fileList{$file}{'owner'} $$fileList{$file}{'target'}"
            );
   } # foreach file
   return 1;
}

# parse the flags to decide the actions:
# install - assumes is a new install, overwrites everything
# upgrade - Checks for new files and overwrites only them
# uninstall - Removes everything
# reinstall - overwrites everything with fresh copy

################
# check for the configuration file!!!
################




# figure out if we know our operating system
$status = &getOS( \%install, \%operatingSystems );

$installType = getInstallActions( \%install );

# based on the defaults, flesh out the install hash
$status = &populateSourceDir( \%install, $sourceDir );

$status = &getVersions( \%install );

$status = &doInstall( \%install );


print Dumper( \%install ) if $TESTING > 2;