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;