#!/usr/bin/perl -w =head1 NAME xen-update-image - Update the software installed upon offline Xen images. =head1 SYNOPSIS xen-update-image [options] imageName1 imageName2 .. imageNameN Help Options: --help Show this scripts help information. --manual Read this scripts manual. --version Show the version number and exit. General Options: --dir Specify the directory which contains the image(s). --volume Specify the LVM volume which contains the image(s). =cut =head1 OPTIONS =over 8 =item B<--dir> Specify the directory which contains the image(s). =item B<--help> Show the script help =item B<--manual> Read the manual =item B<--version> Show the version number and exit. =item B<--volume> Specify the LVM volume where images are located. =back =cut =head1 DESCRIPTION xen-update-image is a simple script which allows you to update a Xen image of Debian which has been created with xen-create-image. It does this by mounting the image inside a temporary directory then running: apt-get update apt-get upgrade If the image is already running within Xen this will cause corruption otherwise it will allow you to update your image without booting it. =cut =head1 EXAMPLES The following assumes there are two images which are not currently running. The images are called 'test.my.flat', and 'x11.my.flat'. Updating both images can be accomplished by executing: xen-update-images --dir=/home/xen test.my.flat x11.my.flat =cut =head1 AUTHOR Steve -- http://www.steve.org.uk/ $Id: xen-update-image,v 1.29 2006-06-09 09:27:33 steve Exp $ =cut =head1 LICENSE Copyright (c) 2005-2006 by Steve Kemp. 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 English; use File::Temp qw/ tempdir /; use Getopt::Long; use Pod::Usage; # # Configuration options, initially read from the configuration file # but may be overridden by the command line. # # Command line flags *always* take precedence over the configuration file. # my %CONFIG; # # Release number. # my $RELEASE = '1.6'; # # Read configuration file if it exists. # if ( -e "/etc/xen-tools/xen-tools.conf" ) { readConfigurationFile( "/etc/xen-tools/xen-tools.conf" ); } # # Parse command line arguments, these override the values from the # configuration file. # parseCommandLineArguments(); # # Make sure we have either a volume, or a root. # if ( $CONFIG{'volume'} && $CONFIG{'dir'} ) { print "Please only use a volume or a directory name - not both\n"; exit; } # # Volumes are not supported yet :( # if ( $CONFIG{'volume'} ) { print "LVM Volumes are not supported yet\n"; exit; } # # Abort if non-root user. # if ( $EFFECTIVE_USER_ID != 0 ) { print < 1 ); my $mount_cmd = "mount -t auto -o loop $image $tmp"; `$mount_cmd`; # # Make sure this is a Debian image. # if ( ( -e $tmp . "/usr/bin/apt-get" ) && ( -e $tmp . "/etc/apt/sources.list" ) ) { # # Now run the update command. # system( "chroot $tmp /usr/bin/apt-get update" ); # # Now upgrade # system( "DEBIAN_FRONTEND=noninteractive chroot $tmp /usr/bin/apt-get upgrade --yes --force-yes" ); } else { print "Xen image $name is not a Debian GNU/Linux image. Skipping\n"; } # # Unmount # `umount $tmp`; } =head2 readConfigurationFile Read the configuration file specified. =cut sub readConfigurationFile { my ($file) = ( @_ ); open( FILE, "<", $file ) or die "Cannot read file '$file' - $!"; my $line = ""; while (defined($line = ) ) { chomp $line; if ($line =~ s/\\$//) { $line .= ; redo unless eof(FILE); } # Skip lines beginning with comments next if ( $line =~ /^([ \t]*)\#/ ); # Skip blank lines next if ( length( $line ) < 1 ); # Strip trailing comments. if ( $line =~ /(.*)\#(.*)/ ) { $line = $1; } # Find variable settings if ( $line =~ /([^=]+)=([^\n]+)/ ) { my $key = $1; my $val = $2; # Strip leading and trailing whitespace. $key =~ s/^\s+//; $key =~ s/\s+$//; $val =~ s/^\s+//; $val =~ s/\s+$//; # Store value. $CONFIG{ $key } = $val; } } close( FILE ); } =head2 parseCommandLineArguments Parse the arguments specified upon the command line. =cut sub parseCommandLineArguments { my $HELP = 0; my $MANUAL = 0; my $VERSION = 0; # Parse options. # GetOptions( "dir=s", \$CONFIG{'dir'}, "volume=s", \$CONFIG{'volume'}, "help", \$HELP, "manual", \$MANUAL, "version", \$VERSION ); pod2usage(1) if $HELP; pod2usage(-verbose => 2 ) if $MANUAL; if ( $VERSION ) { my $REVISION = '$Revision: 1.29 $'; if ( $REVISION =~ /1.([0-9.]+) / ) { $REVISION = $1; } print "xen-update-image release $RELEASE - CVS: $REVISION\n"; exit; } }