#!/usr/bin/perl # # Script to update NCM components in a configuration DB based on QWG templates # from the version in Quattor CVS. # # Written by Michel Jouvin - LAL / CNRS - use strict; use File::Basename; use Getopt::Long; my @component_root; my $norpm = 0; my $rpm_repository; my $source; my $verbose = 0; # Process the script arguments my %options = (); &GetOptions(\%options, "comp_dir=s", "help", "norpm", "rpmrep=s", "source=s", "verbose+") or usage(); if ( defined($options{help}) ) { usage('full'); } if ( defined($options{verbose}) ) { $verbose = $options{verbose}; } unless ( defined($options{source}) ) { print STDERR "Error: no source specified for components\n"; usage(); } unless ( @ARGV > 0 ) { print STDERR "Error: no component specified\n"; exit 2; } $source = $options{source}; $source =~ s%/$%%; if ( !-d $source ) { print STDERR "Error : component source ($source) doesn't exist\n"; exit 2; } if ( defined($options{comp_dir}) ) { push @component_root, $options{comp_dir}; } else { my $comp_category = basename($source); if ( $comp_category eq 'core' ) { push @component_root, 'cfg/standard/components'; } else { opendir(GRIDTEMPL, 'cfg/grid') || die 'Error reading cfg/grid directory'; my @grid_versions = grep /^[^\.]/, readdir(GRIDTEMPL); closedir (GRIDTEMPL); foreach my $version (@grid_versions) { push @component_root, 'cfg/grid/'.$version.'/components'; } } } foreach my $install_root (@component_root) { unless ( -d $install_root ) { print STDERR "Error: installation directory for templates ($install_root) doesn't exist\n"; exit 3; } } if ( defined($options{norpm})) { $norpm = 1; } $rpm_repository = $options{rpmrep}; if ( defined($rpm_repository) ) { if ( $norpm ) { print STDERR "Warning: --norpm specified, --rpmrep will be ignored\n" } elsif ( !-d $rpm_repository ) { print STDERR "Error: destination directory for RPM ($rpm_repository) doesn't exist\n"; exit 3; } } if ( $verbose ) { print "\n"; print "Component source = $source\n"; foreach (@component_root) { print "Installation directory for templates = $_\n"; } if ( defined($rpm_repository) ) { print "Installation directory for RPM = $rpm_repository\n"; } else { print "Don't install component RPM\n"; } print "Verbosity level = $verbose\n"; } # Rebuild and install each component foreach my $component (@ARGV) { print STDERR "\nBuilding component $component...\n"; my $comp_source = "$source/ncm-$component"; # It is necessary to run 'make clean' to be sure that templates # are built with the correct version my @output = qx%cd $comp_source; make clean; make; make BUILDVERBOSE=1 rpm 2>&1%; unless ( $? == 0 ) { print STDERR "Error rebuilding component\n"; exit 6; } if ( $verbose > 1 ) { foreach (@output) { print "$_"; } } my $rpm_path; my @rpm_path_line = grep /^Wrote:.*noarch\.rpm/, @output; if ( @rpm_path_line ) { (my $dummy, $rpm_path) = split /:\s*/, $rpm_path_line[0]; chomp $rpm_path; unless ( $rpm_path ) { print STDERR "Error: RPM name is empty\n"; exit 7; } } foreach my $install_dir (@component_root) { print STDERR "Installing component $component templates in $install_dir..\n"; my $comp_dir = $install_dir.'/'.$component; my $add_to_svn = 0; if ( !-d $comp_dir ) { unless ( mkdir $comp_dir ) { print STDERR "Error creating directory $comp_dir: $!\n"; exit 4; } $add_to_svn = 1; } my $status = system("cp $comp_source/TPL/*.tpl $comp_dir"); unless ( $status == 0 ) { print STDERR "Error copying templates to $comp_dir\n"; exit 4; } if ( $norpm ) { # Check component is made only of Perl module (no DATA directory) # FIXME : add support for DATA directory in RPM-less component using data nlist attribute if ( -d "$comp_dir/DATA" ) { print "Error: RPM-less component is not a supported option for $component (DATA directory exists)\n"; exit 5; } my $code_template_file = $comp_dir . '/code.tpl'; print STDERR "Inlining component code into $code_template_file...\n"; # Read the component code my $comp_code_file = "$comp_source/$component.pm"; open (COMPCODE, $comp_code_file) || die "Error opening component code ($comp_code_file)"; my @comp_code = ; close COMPCODE; # Build a template with component code inlined my $code_template_name = 'components/' . $component . '/code'; open (TEMPL, ">$code_template_file") || die "Cannot create $code_template_file"; print TEMPL "unique template $code_template_name;\n\n"; print TEMPL "'/software/components/$component/code/script' = <; close COMPCONFIG; open (COMPCONFIG, ">$comp_config_template") || die "Error creating component config.tpl ($comp_config_template)"; foreach my $line (@comp_config) { if ( $line =~ /pkg_repl/ ) { $line = "include { '$code_template_name' };\n"; } elsif ( $line =~ /spma/ ) { $line =~ s/['"]spma['"]\s*//; } print COMPCONFIG $line; } close COMPCONFIG; } my $status = system("chmod u+w $comp_dir/*.tpl"); if ( $add_to_svn ) { my $status = system("svn add $comp_dir"); unless ( $status == 0 ) { print STDERR "Error adding templates to SVN"; exit 4; } # If the namespaced version of this component is new, remove old # templates if any if ( -f "$install_dir/pro_software_component_$component.tpl" ) { my $status = system("svn rm $install_dir/pro_*$component.tpl"); unless ( $status == 0 ) { print STDERR "Warning : error deleting $component non namespaced templates"; } } } } if ( ! $norpm && defined($rpm_repository) ) { if ( defined($rpm_path) ) { my $rpm_name = basename($rpm_path); print STDERR "Installing component $component RPM ($rpm_name) in $rpm_repository..\n"; my $status = system("cp $rpm_path $rpm_repository"); unless ( $status == 0 ) { print STDERR "Error copying RPM $rpm_path to $rpm_repository\n"; exit 5; } } else { print STDERR "Failed to retrieve RPM name : cannot copy it to $rpm_repository\n"; } } } # Print the usage instructions for this script. sub usage { my $usage_only = 1; if ( (@_ == 1) && ($_[0] eq 'full') ) { $usage_only = 0; } print << 'EOF' This script update 1 or several NCM components from sources. This includes installing the new version of component templates into SCDB and, optionally, copying new RPMs to the appropriate RPM repository. If the component doesn't exist yet in SCDB, it is added. The only requirement to run this script is to have an up-to-date copy of Quattor CVS ncm-components/ directory. Usage: updateComponent [--comp_dir SCDB_comp_dir] \ [--norpm] \ [--rpmrep RPM_repository] \ [--verbose] \ --source comp_source \ component [component...] EOF ; if ( $usage_only ) { print "\tFor detailed information about options, use --help.\n\n"; } elsif ( $usage_only ) { print <