#!/usr/bin/perl -w =head1 NAME xen-duplicate-image - Duplicate an existing Xen instance. =head1 SYNOPSIS xen-duplicate-image [options] Help Options: --help Show this scripts help information. --manual Read this scripts manual. --version Show the version number and exit. General options: --dir Specify where the output images should go. Networking options: --dhcp Setup the image to get an IP address via DHCP --network Setup the network the host is upon. --netmask Setup the netmask the host should use. --gateway Setup the iamge's network gateway. --broadcast Setup the image's network broadcast address. Mandatory options: --hostname Set the images hostname. --from The image name we should copy =cut =head1 OPTIONS =over 8 =item B<--boot> Boot the new instance immediately after creating it. =item B<--broadcast> Specify the broadcast address for the virtual image, only useful if DHCP is not used. =item B<--dhcp> Specify that the virtual image should use DHCP to obtain its networking information. =item B<--gateway> Specify the gateway address for the virtual image, only useful if DHCP is not used. =item B<--help> Show the brief help information. =item B<--manual> Read the manual, with examples. =item B<--netmask> Setup the netmask the host should use. =item B<--network> Specify the network the virtual image is living upon. Only useful if DHCP is not used. =item B<--from> Specify the virtual instance that we should copy. =item B<--version> Show the version number and exit. =back =cut =head1 EXAMPLES The following will copy the existing image vm01, and save it as vm02 - with DHCP enabled. xen-duplicate-image --dir=/home/xen \ --from=vm01 --hostname=vm02.my.flat --dhcp =cut =head1 DESCRIPTION xen-duplicate-image is a simple script which allows you to create new Xen instances of Debian Sarge. The new image will be an identical copy of an existing image. =head1 CONFIGURATION To reduce the length of the command line each of the options may be specified inside a configuration file. The script will check two files for options: 1. /etc/xen-tools/xen-tools.conf 2. ~/.xen-tools.conf The files may contain comments, which begin with the hash '#' character and are otherwise of the format 'key = value. =head1 AUTHOR Steve -- http://www.steve.org.uk/ $Id: xen-duplicate-image,v 1.8 2005-12-21 22:46:36 steve Exp $ =cut =head1 CONTRIBUTORS Radu Spineanu =head1 LICENSE Copyright (c) 2005 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::Copy; use File::Temp qw/ tempdir /; use Getopt::Long; use Pod::Usage; # # Configuration options, initially read from the configuration files # but may be overridden by the command line. # # Command line flags *always* take precedence over the configuration files(s). # my %CONFIG; # # Defaults # $CONFIG{'xm'} = '/usr/sbin/xm'; # # Read configuration file(s) if they exist. # if ( -e "/etc/xen-tools/xen-tools.conf" ) { readConfigurationFile( "/etc/xen-tools/xen-tools.conf" ); } if ( -e $ENV{'HOME'} . ".xen-tools.conf" ) { readConfigurationFile( $ENV{'HOME'} . ".xen-tools.conf" ); } # # Parse command line arguments, these override the values from the # configuration file. # parseCommandLineArguments(); # # Check that the arguments the user has supplied are both # valid, and complete. # checkArguments(); if ( $EFFECTIVE_USER_ID != 0 ) { print < 1 ); my $mount_cmd = "mount -t auto -o loop $image_out $dir"; `$mount_cmd`; # Test that the mount worked my $mount = `/bin/mount`; if ( ! $mount =~ /$image_out/) { print "Something went wrong trying to mount the new filesystem\n"; exit; } # # Setup the output directories for the configuration files here - note # that this should already exist. # `mkdir -p $dir/etc/apt`; `mkdir -p $dir/etc/network`; # # Setup the /etc/network/interfaces file upon the guest image # setupNetworking( $dir ); # # Now unmount the image. # `umount $dir`; # # Finally setup Xen to allow us to create the image. # print "Setting up Xen configuration file .. "; open( XEN, ">", "/etc/xen/$CONFIG{'hostname'}.cfg" ); print XEN<) ) { 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( "hostname=s", \$CONFIG{'hostname'}, "from=s", \$CONFIG{'from'}, "ip=s", \$CONFIG{'ip'}, "gateway=s", \$CONFIG{'gateway'}, "mask=s", \$CONFIG{'netmask'}, "broadcast=s",\$CONFIG{'broadcast'}, "network=s", \$CONFIG{'network'}, "dir=s", \$CONFIG{'dir'}, "dhcp", \$CONFIG{'dhcp'}, "help", \$HELP, "manual", \$MANUAL, "version", \$VERSION ); pod2usage(1) if $HELP; pod2usage(-verbose => 2 ) if $MANUAL; if ( $VERSION ) { my $REVISION = '$Id: xen-duplicate-image,v 1.8 2005-12-21 22:46:36 steve Exp $'; $VERSION = join (' ', (split (' ', $REVISION))[2]); $VERSION =~ s/,v\b//; $VERSION =~ s/(\S+)$/$1/; print "xen-duplicate-image release 0.5 - CVS: $VERSION\n"; exit; } } =head2 checkArguments Check that the arguments the user has specified are complete and make sense. =cut sub checkArguments { if (!defined( $CONFIG{'hostname'} ) ) { print< $prefix/etc/hostname`; open( IP, ">", $prefix . "/etc/network/interfaces" ); if ( $CONFIG{'dhcp'} ) { print IP<