352 lines
7.7 KiB
Perl
Executable File
352 lines
7.7 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
|
|
=encoding utf8
|
|
|
|
=head1 NAME
|
|
|
|
xt-customize-image - Customize a freshly installed copy of GNU/Linux
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
xt-customize-image [options]
|
|
|
|
Help Options:
|
|
--help Show this scripts help information.
|
|
--manual Read this scripts manual.
|
|
--version Show the version number and exit.
|
|
|
|
Debugging Options:
|
|
--verbose Be verbose in our execution.
|
|
|
|
Mandatory Options:
|
|
--location The location of the new installation
|
|
--dist The name of the distribution which has been installed.
|
|
|
|
All other options from xen-create-image, such as the new IP address(es)
|
|
to give to the new instance, will be passed as environmental variables.
|
|
|
|
|
|
=head1 NOTES
|
|
|
|
This script is invoked by xen-create-image after it has created a
|
|
fresh installation of Linux within a temporary location.
|
|
|
|
This script will be invoked with a full copy of the arguments from
|
|
xen-create-image in its environment, along with several command line
|
|
arguments.
|
|
|
|
The command line arguments which are mandatory are:
|
|
|
|
--location - The temporary installation root of the new install
|
|
--dist - The distribution which has been installed.
|
|
|
|
|
|
=head1 HOOK SCRIPTS
|
|
|
|
The distribution name is used to locate an appropriate collection
|
|
of scripts, or hooks, to execute to do the actual customisation.
|
|
|
|
The hooks will each be executed with a single parameter which is
|
|
the directory path to the new instance. This argument is taken from
|
|
the --location option.
|
|
|
|
For the distribution named 'foo' the scripts will be loaded and
|
|
executed from '/usr/share/xen-tools/foo.d'. Each executable will
|
|
be loaded and executed in sorted order.
|
|
|
|
The systems administrator can optionally provide site-specific
|
|
revisions of those same hooks by placing them in the directory
|
|
'/etc/xen-tools/hooks.d/' in which case a script with the same name
|
|
as the one in the 'foo.d' directory above will take precedence. In
|
|
this way certain hooks can be prevented from running, expanded with
|
|
site-specific features which won't get overwritten on upgrades, or
|
|
patched with critical bug-fixes before the upstream OS distribution
|
|
provider reacts.
|
|
|
|
|
|
=head1 AUTHORS
|
|
|
|
Steve Kemp, https://steve.fi/
|
|
Axel Beckert, https://axel.beckert.ch/
|
|
Stéphane Jourdois
|
|
|
|
|
|
=head1 LICENSE
|
|
|
|
Copyright (c) 2005-2009 by Steve Kemp, (c) 2010 by The Xen-Tools
|
|
Development Team. All rights reserved.
|
|
|
|
This module is free software;
|
|
you can redistribute it and/or modify it under
|
|
the same terms as Perl itself.
|
|
The LICENSE file contains the full text of the license.
|
|
|
|
=cut
|
|
|
|
|
|
use strict;
|
|
use Env;
|
|
use Getopt::Long;
|
|
use Pod::Usage;
|
|
|
|
|
|
#
|
|
# Configuration values read from the command line.
|
|
#
|
|
# We do not need to read any configuration file.
|
|
#
|
|
my %CONFIG;
|
|
|
|
#
|
|
# Release number.
|
|
#
|
|
my $RELEASE = '4.6.2';
|
|
|
|
|
|
|
|
#
|
|
# Parse the command line arguments.
|
|
#
|
|
parseCommandLineArguments();
|
|
|
|
|
|
#
|
|
# Check our arguments.
|
|
#
|
|
checkArguments();
|
|
|
|
|
|
#
|
|
# Run each relevant hook scripts.
|
|
#
|
|
runDistributionHooks();
|
|
|
|
|
|
#
|
|
# Exit cleanly - any errors which have already occurred will result
|
|
# in "exit 1".
|
|
#
|
|
exit 0;
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
Parse the command line arguments this script was given.
|
|
|
|
=end doc
|
|
|
|
=cut
|
|
|
|
sub parseCommandLineArguments
|
|
{
|
|
my $HELP = 0;
|
|
my $MANUAL = 0;
|
|
my $VERSION = 0;
|
|
|
|
#
|
|
# Parse options.
|
|
#
|
|
GetOptions( "location=s", \$CONFIG{ 'location' },
|
|
"dist=s", \$CONFIG{ 'dist' },
|
|
"verbose", \$CONFIG{ 'verbose' },
|
|
"help", \$HELP,
|
|
"manual", \$MANUAL,
|
|
"version", \$VERSION
|
|
);
|
|
|
|
pod2usage(1) if $HELP;
|
|
pod2usage( -verbose => 2 ) if $MANUAL;
|
|
|
|
|
|
if ($VERSION)
|
|
{
|
|
print "xt-customize-image release $RELEASE\n";
|
|
exit;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
Test that the command line arguments we were given make sense.
|
|
|
|
=end doc
|
|
|
|
=cut
|
|
|
|
sub checkArguments
|
|
{
|
|
|
|
#
|
|
# We require a location.
|
|
#
|
|
if ( !defined( $CONFIG{ 'location' } ) )
|
|
{
|
|
print "The '--location' argument is mandatory\n";
|
|
exit 1;
|
|
}
|
|
|
|
|
|
#
|
|
# Test that the location we've been given exists
|
|
#
|
|
if ( !-d $CONFIG{ 'location' } )
|
|
{
|
|
print "The installation directory we've been given doesn't exist\n";
|
|
print "We tried to use : $CONFIG{'location'}\n";
|
|
exit 1;
|
|
}
|
|
|
|
|
|
#
|
|
# We require a distribution name.
|
|
#
|
|
if ( !defined( $CONFIG{ 'dist' } ) )
|
|
{
|
|
print "The '--dist' argument is mandatory\n";
|
|
exit 1;
|
|
}
|
|
|
|
|
|
#
|
|
# Test that the distribution name we've been given
|
|
# to configure has a collection of hook scripts.
|
|
#
|
|
# If there are no scripts then we clearly cannot
|
|
# customise it!
|
|
#
|
|
my $dir = "/usr/share/xen-tools/" . $CONFIG{ 'dist' } . ".d";
|
|
|
|
if ( !-d $dir )
|
|
{
|
|
print <<E_OR;
|
|
|
|
We\'re trying to configure an installation of $CONFIG{'dist'} in
|
|
$CONFIG{'location'} - but there is no hook directory for us to use.
|
|
|
|
This means we don\'t know how to configure this installation.
|
|
|
|
We\'d expect the hook directory to be : $dir
|
|
|
|
Aborting.
|
|
E_OR
|
|
exit 1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
This function does the real work of running each of our hook scripts.
|
|
|
|
Each hook script is executed in turn, ignoring emacs save files and
|
|
dpkg files.
|
|
|
|
We will give each script the name of the directory containing the
|
|
installation as a single argument.
|
|
|
|
=end doc
|
|
|
|
=cut
|
|
|
|
sub runDistributionHooks
|
|
{
|
|
|
|
#
|
|
# Hook directory.
|
|
#
|
|
my $hooks = "/usr/share/xen-tools/" . $CONFIG{ 'dist' } . ".d/";
|
|
my $hooks_local = "/etc/xen-tools/hooks.d/";
|
|
|
|
#
|
|
# Installation prefix
|
|
#
|
|
my $prefix = $CONFIG{ 'location' };
|
|
|
|
#
|
|
# If we're running verbosely then setup the client environment
|
|
# appropriately.
|
|
#
|
|
# This is useful in case this script is called outwith the usual
|
|
# xen-create-image framework.
|
|
#
|
|
if ( $CONFIG{ 'verbose' } )
|
|
{
|
|
$ENV{ 'verbose' } = 1;
|
|
}
|
|
|
|
#
|
|
# Make sure that our scripts run in sorted order, as
|
|
# the user would expect.
|
|
#
|
|
foreach my $file ( sort( glob( $hooks . "*" ) ) )
|
|
{
|
|
|
|
# skip files that end with .dpkg-new, .dpkg-old or '~'
|
|
next if ( $file =~ /\.dpkg-(new|old)/ );
|
|
next if ( $file =~ /~$/ );
|
|
|
|
#
|
|
# Only run executable files.
|
|
#
|
|
if ( ( -x $file ) && ( -f $file ) )
|
|
{
|
|
|
|
#
|
|
# Just display the name - no need to see the full path.
|
|
#
|
|
my $name = $file;
|
|
if ( $file =~ /(.*)\/(.*)/ )
|
|
{
|
|
$name = $2;
|
|
}
|
|
|
|
#
|
|
# Run a local version of the hook instead of the system one,
|
|
# if the local one exists and is executable.
|
|
#
|
|
my $file_local = $hooks_local . $name;
|
|
if ( ( -x $file_local ) && ( -f $file_local ) )
|
|
{
|
|
$file = $file_local
|
|
}
|
|
|
|
#
|
|
# Complete command we're going to execute.
|
|
#
|
|
my $cmd = $file . " $CONFIG{'location'}";
|
|
|
|
#
|
|
# Run the command. This has different prolog and epilog
|
|
# depending on whether we're running verbosely or not.
|
|
#
|
|
if ( $CONFIG{ 'verbose' } )
|
|
{
|
|
print "Running hook $name ['$cmd']\n";
|
|
print "--\n";
|
|
my $rc = system($cmd);
|
|
if ($rc != 0) {
|
|
print "hook $name failed: $?\n";
|
|
exit 1;
|
|
}
|
|
print "--\n";
|
|
print "Done\n\n";
|
|
}
|
|
else
|
|
{
|
|
print "Running hook $name\n";
|
|
my $rc = system($cmd);
|
|
if ($rc != 0) {
|
|
print "hook $name failed: $?\n";
|
|
exit 1;
|
|
}
|
|
print "hook $name: done.\n";
|
|
}
|
|
}
|
|
}
|
|
}
|