Author: arkurth Date: Mon Feb 6 17:18:25 2012 New Revision: 1241083 URL: http://svn.apache.org/viewvc?rev=1241083&view=rev Log: VCL-545 Updated install_perl_libs.pl. Fixed problem where Perl modules failed to install if "notest" function is not available from the CPAN module. This function is only available on newer versions.
Added -l and -p arguments to allow only Linux packages or Perl modules to be installed -- useful for testing the script. Added LWP::Protocol::https to list of Perl modules to install. Modified: incubator/vcl/trunk/managementnode/bin/install_perl_libs.pl Modified: incubator/vcl/trunk/managementnode/bin/install_perl_libs.pl URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/bin/install_perl_libs.pl?rev=1241083&r1=1241082&r2=1241083&view=diff ============================================================================== --- incubator/vcl/trunk/managementnode/bin/install_perl_libs.pl (original) +++ incubator/vcl/trunk/managementnode/bin/install_perl_libs.pl Mon Feb 6 17:18:25 2012 @@ -53,27 +53,53 @@ use POSIX; # Store the command line options in hash my $AGREE; +my $INSTALL_LINUX_PACKAGES; +my $INSTALL_PERL_MODULES; my %OPTIONS; GetOptions(\%OPTIONS, 'y!' => \$AGREE, + 'linux!' => \$INSTALL_LINUX_PACKAGES, + 'perl!' => \$INSTALL_PERL_MODULES, + 'help' => \&help, ); show_disclaimer() if !$AGREE; -my @ERRORS; +my $ERRORS = {}; -print_break('='); -install_linux_packages(); +# Check if -l or -y was specified +if (!defined($INSTALL_PERL_MODULES) && !defined($INSTALL_LINUX_PACKAGES)) { + $INSTALL_PERL_MODULES = 1; + $INSTALL_LINUX_PACKAGES = 1; +} +elsif (defined($INSTALL_PERL_MODULES) && !defined($INSTALL_LINUX_PACKAGES)) { + $INSTALL_LINUX_PACKAGES = !$INSTALL_PERL_MODULES; +} +elsif (defined($INSTALL_LINUX_PACKAGES) && !defined($INSTALL_PERL_MODULES)) { + $INSTALL_PERL_MODULES = !$INSTALL_LINUX_PACKAGES; +} -print_break('='); -install_perl_modules(); +if ($INSTALL_LINUX_PACKAGES) { + print_break('='); + install_linux_packages(); +} + +if ($INSTALL_PERL_MODULES) { + print_break('='); + install_perl_modules(); +} print_break('='); -if (@ERRORS) { - print "WARNING: failed to install the following components:\n" . join("\n", @ERRORS) . "\n"; +my $error_encountered; +for my $key (keys %$ERRORS) { + for my $component (sort keys %{$ERRORS->{$key}}) { + print "WARNING: failed to install $key: $component\n"; + $error_encountered++; + } } -else { + +if (!$error_encountered) { print "COMPLETE: installed all components\n"; } @@ -81,11 +107,20 @@ exit; #///////////////////////////////////////////////////////////////////////////// +=head2 install_linux_packages + + Parameters : none + Returns : boolean + Description : Installs the Linux operating system packages required by the VCL + managment node components. + +=cut + sub install_linux_packages { # Check if yum is available my ($which_exit_status, $which_output) = run_command("which yum"); if ($which_exit_status ne '0') { - print "yum is not available on this OS, skipping Linux package installation\n"; + print "WARNING: yum is not available on this OS, skipping Linux package installation\n"; return 0; } @@ -119,14 +154,14 @@ sub install_linux_packages { if ($wget_exit_status eq '0' && $wget_output =~ /(epel-release-[\d-]+\.noarch\.rpm)/) { my $rpm_file_name = $1; $epel_url .= "/$rpm_file_name"; - print "constructed EPEL URL: '$epel_url'\n\n"; + print "Constructed EPEL URL: '$epel_url'\n\n"; # Download the EPEL RPM file my $rpm_command = "rpm -Uvh $epel_url"; my ($rpm_exit_status, $rpm_output) = run_command($rpm_command); if ($rpm_exit_status ne '0' && $rpm_output !~ /already installed/i) { print "WARNING: failed to install EPEL, some Perl modules may not install correctly\nrpm command: $rpm_command\nrpm exit status: $rpm_exit_status\nrpm output:\n$rpm_output\n"; - push @ERRORS, 'EPEL'; + $ERRORS->{'Linux package'}{'EPEL'} = 1; } elsif ($rpm_output =~ /already installed/i) { print "SUCCESS: EPEL is already installed\n"; @@ -137,7 +172,7 @@ sub install_linux_packages { } else { print "WARNING: failed to determine name of EPEL RPM, did not locate 'epel-relase' line in wget output, some Perl modules may not install correctly\nwget command: '$wget_command'\nexit status: $wget_exit_status\noutput:\n$wget_output\n"; - push @ERRORS, 'EPEL'; + $ERRORS->{'Linux package'}{'EPEL'} = 1; } @@ -147,16 +182,13 @@ sub install_linux_packages { } my @linux_packages = ( - 'expat', 'expat-devel', 'gcc', 'krb5-libs', 'krb5-devel', - 'libxml2', 'libxml2-devel', 'make', 'nmap', - 'openssl', 'openssl-devel', 'perl-Archive-Tar', 'perl-CPAN', @@ -175,12 +207,12 @@ sub install_linux_packages { for my $linux_package (@linux_packages) { print_break('*'); - print "Attempting to install Linux package using yum: '$linux_package'\n"; + print "Attempting to install Linux package using yum: $linux_package\n"; - my $yum_command = "yum install $linux_package -y"; - print "yum command: $yum_command\n"; + my $yum_command = "yum install $linux_package -y --nogpgcheck"; + #print "Yum command: $yum_command\n"; - my $yum_output = `$yum_command 2>&1`; + my $yum_output = `$yum_command 2>&1 | grep -v '^\\(Load\\|Setting\\|Nothing\\| \\*\\)'`; my $yum_exit_status = $? >> 8; chomp $yum_output; @@ -188,32 +220,44 @@ sub install_linux_packages { if ($yum_exit_status ne '0') { print "WARNING: failed to install Linux package: '$linux_package', exit status: $yum_exit_status\n"; - #push @ERRORS, "Linux package: $linux_package"; + $ERRORS->{'Linux package'}{$linux_package} = 1; } elsif ($yum_output =~ /$linux_package[^\n]*already installed/i) { - print "SUCCESS: Linux package is already installed: '$linux_package'\n"; + print "SUCCESS: Linux package is already installed: $linux_package\n"; } elsif ($yum_output =~ /Complete\!/i) { - print "SUCCESS: installed Linux package: '$linux_package'\n"; + print "SUCCESS: installed Linux package: $linux_package\n"; + } + elsif ($yum_output =~ /No package.*available/i) { + print "WARNING: Linux package is not available via yum: $linux_package\n"; + $ERRORS->{'Linux package'}{$linux_package} = 1; } else { - print "WARNING: unexpected output returned while installing Linux package: '$linux_package'\n"; - #push @ERRORS, "Linux package: $linux_package"; + print "WARNING: unexpected output returned while installing Linux package: $linux_package\n"; + $ERRORS->{'Linux package'}{$linux_package} = 1; } - } - return 1; } #///////////////////////////////////////////////////////////////////////////// -sub install_perl_modules { - - eval "use CPAN"; +=head2 configure_cpan + + Parameters : none + Returns : boolean + Description : Attempts to configure CPAN so that modules can be installed + without user interaction. + +=cut + +sub configure_cpan { + eval { + require CPAN; + }; if ($EVAL_ERROR) { - print "ERROR: CPAN Perl module is not installed, unable to install other Perl module dependencies\n"; - exit; + print "Unable to install Perl modules, CPAN module could not be loaded.\n"; + exit 1; } $ENV{PERL_MM_USE_DEFAULT} = 1; @@ -236,9 +280,7 @@ sub install_perl_modules { "check_sigs" => "0", "connect_to_internet_ok" => "1", "cpan_home" => "$cpan_directory", - "debug" => "all", "curl" => `echo -n \`which curl\`` || "", - "force" => "1", "ftp" => `echo -n \`which ftp\`` || "", "ftp_passive" => "1", "ftp_proxy" => "", @@ -253,7 +295,6 @@ sub install_perl_modules { "index_expire" => "10", "inhibit_startup_message" => "1", "keep_source_where" => "$cpan_directory/sources", - "links" => `echo -n \`which links\`` || "", "load_module_verbosity" => "1", "make" => `echo -n \`which make\`` || "", "make_arg" => "", @@ -278,7 +319,7 @@ sub install_perl_modules { "shell" => `echo -n \`which bash\`` || "", "show_upload_date" => "0", "tar" => `echo -n \`which tar\`` || "", - "tar_verbosity" => "0", + "tar_verbosity" => "", "term_ornaments" => "1", "trust_test_report_history" => "1", "unzip" => `echo -n \`which unzip\`` || "", @@ -290,36 +331,94 @@ sub install_perl_modules { eval { CPAN::Config->commit($config_file_path) }; if ($EVAL_ERROR) { - print Dumper($CPAN::Config) . "\n"; - + print format_data($CPAN::Config) . "\n"; + print "\nERROR: failed to create CPAN configuration file: $config_file_path\n"; exit 1; } else { - print "created CPAN configuration file: $config_file_path\n"; + print "Created CPAN configuration file: $config_file_path\n"; } - print_cpan_configuration(); +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 install_perl_modules + + Parameters : + Returns : + Description : + +=cut + +sub install_perl_modules { + eval { require CPAN }; + if ($EVAL_ERROR) { + print "ERROR: failed to install perl modules, CPAN module is not available\n"; + $ERRORS->{'Perl module'}{'ALL'} = 1; + return; + } + configure_cpan(); + my @perl_modules = ( + 'CPAN', 'DBI', 'Digest::SHA1', + 'LWP::Protocol::https', 'Mail::Mailer', 'Object::InsideOut', 'RPC::XML', + 'URI', 'YAML', ); - for my $perl_module (@perl_modules) { - print_break('-'); - print "Attempting to install Perl module using CPAN: '$perl_module'\n"; - - eval { CPAN::Shell->notest("install", $perl_module) }; - #eval { CPAN::Shell->install($perl_module) }; - - if (!is_perl_module_installed($perl_module)) { - print "ERROR: failed to install Perl module: '$perl_module'\n"; - push @ERRORS, "Perl module: $perl_module"; + PERL_MODULE: for my $perl_module (@perl_modules) { + print_break('*'); + + my $cpan_version = get_perl_module_cpan_version($perl_module); + if (!$cpan_version) { + print "ERROR: unable to install $perl_module Perl module, information could not be obtained from CPAN\n"; + $ERRORS->{'Perl module'}{$perl_module} = 1; + next PERL_MODULE; + } + + # Check if installed version matches what is available from CPAN + my $installed_version = get_perl_module_installed_version($perl_module); + if ($installed_version && $installed_version eq $cpan_version) { + print "$perl_module Perl module is up to date\n"; + } + else { + + # Check if the CPAN module implements the "notest" method + # This is not available in older versions of CPAN.pm + if (CPAN::Shell->can('notest')) { + print "Attempting to install (notest, force) Perl module using CPAN: $perl_module\n"; + eval { CPAN::Shell->rematein("notest", "force", "install", $perl_module) }; + #eval { CPAN::Shell->notest("force install", $perl_module) }; + } + else { + print "Attempting to install (force) Perl module using CPAN: $perl_module\n"; + eval { CPAN::Shell->rematein("force", "install", $perl_module) }; + #eval { CPAN::Shell->force("install", $perl_module) }; + } + + # Check if the module was successfully installed + $installed_version = get_perl_module_installed_version($perl_module); + if (!$installed_version) { + print "ERROR: failed to install $perl_module Perl module\n"; + $ERRORS->{'Perl module'}{$perl_module} = 1; + next PERL_MODULE; + } + } + + # Check if corresponding Linux package failed - remove from %ERRORS + my $linux_package_name = "perl-$perl_module"; + $linux_package_name =~ s/::/-/g; + if (defined $ERRORS->{'Linux package'}{$linux_package_name}) { + print "Removed $linux_package_name from list of failed Linux packages\n"; + delete $ERRORS->{'Linux package'}{$linux_package_name}; } } @@ -329,47 +428,116 @@ sub install_perl_modules { #///////////////////////////////////////////////////////////////////////////// -sub is_perl_module_installed { - my $module_package = shift; - - print "checking if $module_package Perl module is installed...\n"; - - my $command = "perl -e \"eval \\\"use $module_package\\\"; print \\\$" . $module_package . "::VERSION\" 2>&1"; - my $output = `$command`; - - my $exit_status = $? >> 8; - #print "checked if $module_package is installed, version check output:\n$output\n"; +=head2 get_perl_module_installed_version + + Parameters : $perl_module + Returns : + Description : + +=cut + +sub get_perl_module_installed_version { + my $perl_module = shift; - if ($output =~ /Can't locate/i) { - print "$module_package Perl module is NOT installed\n"; - return; + my $cpan_module = CPAN::Shell->expand("Module", $perl_module); + if ($cpan_module) { + my $cpan_installed_version = $cpan_module->inst_version; + + if ($cpan_installed_version) { + print "$perl_module $cpan_installed_version Perl module is installed\n"; + return $cpan_installed_version; + } + else { + print "$perl_module Perl module is NOT installed\n"; + return; + } } + else { + print "$perl_module Perl module information could not be obtained from CPAN, checking if it is installed on local computer\n"; + + my $command = "perl -e \"eval \\\"use $perl_module\\\"; print \\\$" . $perl_module . "::VERSION\" 2>&1"; + my $output = `$command`; + my $exit_status = $? >> 8; + + if ($output =~ /Can't locate/i) { + print "$perl_module Perl module is NOT installed\n"; + return; + } + + my ($version) = $output =~ /^(\d[\d\.]+\d)$/; + if (defined($version)) { + print "$perl_module Perl module is installed, version: $version\n"; + return $version; + } + else { + print "$perl_module Perl module appears to be installed but the version could not be determined\ncommand: $command\noutput:\n$output\n"; + return; + } + } +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 get_perl_module_cpan_version + + Parameters : $perl_module + Returns : + Description : + +=cut + +sub get_perl_module_cpan_version { + my $perl_module = shift; - my ($version) = $output =~ /^(\d[\d\.]+\d)$/; - if (defined($version)) { - print "$module_package $version Perl module is installed\n"; - return $version; + my $cpan_module = CPAN::Shell->expand("Module", $perl_module); + if ($cpan_module) { + my $cpan_source_version = $cpan_module->cpan_version; + + if ($cpan_source_version) { + print "$perl_module $cpan_source_version Perl module is available from CPAN\n"; + return $cpan_source_version; + } + else { + print "WARNING: $perl_module Perl module appears to be available from CPAN but version could not be obtained\n"; + return; + } } else { - print "Perl module $module_package appears to be installed but the version could not be determined\ncommand: $command\noutput:\n$output"; + print "WARNING: $perl_module Perl module is NOT available from CPAN\n"; return; } } #///////////////////////////////////////////////////////////////////////////// +=head2 run_command + + Parameters : $command + Returns : array ($exit_status, $output) + Description : + +=cut + sub run_command { my $command = shift; - print "attempting to execute command: '$command'\n"; + print "Attempting to execute command: '$command'\n"; my $output = `$command 2>&1`; my $exit_status = $? >> 8; - print "executed command: '$command', exit status: $exit_status\n"; + print "Executed command: '$command', exit status: $exit_status\n"; return ($exit_status, $output); } #///////////////////////////////////////////////////////////////////////////// +=head2 show_disclaimer + + Parameters : none + Returns : + Description : + +=cut + sub show_disclaimer { my $disclaimer .= <<"EOF"; *** NOTICE *** @@ -406,6 +574,14 @@ EOF #///////////////////////////////////////////////////////////////////////////// +=head2 print_break + + Parameters : $character (optional) + Returns : + Description : + +=cut + sub print_break { my $character = shift; $character = '-' if !defined($character); @@ -414,7 +590,73 @@ sub print_break { #///////////////////////////////////////////////////////////////////////////// -sub print_cpan_configuration { - $Data::Dumper::Sortkeys = 1; - print "CPAN configuration:\n" . Dumper($CPAN::Config) . "\n"; +=head2 format_data + + Parameters : @data + Returns : + Description : + +=cut + +sub format_data { + my @data = @_; + + if (!(@data)) { + return '<undefined>'; + } + + $Data::Dumper::Indent = 1; + $Data::Dumper::Purity = 1; + $Data::Dumper::Useqq = 1; # Use double quotes for representing string values + $Data::Dumper::Terse = 1; + $Data::Dumper::Quotekeys = 1; # Quote hash keys + $Data::Dumper::Pair = ' => '; # Specifies the separator between hash keys and values + $Data::Dumper::Sortkeys = 1; # Hash keys are dumped in sorted order + + my $formatted_string = Dumper(@data); + + my @formatted_lines = split("\n", $formatted_string); + + map { $_ = ": $_" } @formatted_lines; + + return join("\n", @formatted_lines); +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 help + + Parameters : none + Returns : exits + Description : + +=cut + +sub help { + print <<EOF; +Usage: perl $0 [OPTION]... +Install all of the Linux packages and Perl modules required by the VCL +management node daemon (vcld). + + -y skip license agreement + -l, --linux install Linux packages + -p, --perl install Perl modules + --help display this help and exit + +If no -l or -p option is specified, Linux packages and Perl modules are both +installed. +EOF + exit 0; } + +#///////////////////////////////////////////////////////////////////////////// + +1; +__END__ + +=head1 SEE ALSO + +L<http://cwiki.apache.org/VCL/> + +=cut +