#!/usr/bin/perl -w =head1 NAME xen-delete-image - Delete previously created Xen instances. =head1 SYNOPSIS xen-delete-image [options] [--hostname=]imageName1 [--hostname=]imageName2 Help Options: --help Show help information. --manual Read the manual for this script. --version Show the version information and exit. --verbose Show diagnostic output. General options: --dir Specify the output directory where images were previously saved. --evms Specify the EVMS container to use. --lvm Specify the LVM volume to use. Specifying hosts: --hostname Specify the image name to delete. Testing options: --test Don't complain if we're not invoked by root. --no-xen-ok Don't complain if xen seems not installed or xend is not running =cut =head1 OPTIONS =over 8 =item B<--dir> Specify the output directory where images were previously saved. =item B<--evms> Specify the EVMS container where images were previously saved. =item B<--help> Show help information. =item B<--hostname> Specify the hostname to delete. =item B<--lvm> Specify the LVM volume group where images were previously saved. =item B<--manual> Read the manual for this script. =item B<--test> Do not complain, or exit, if the script is not executed by the root user. =item B<--version> Show the version number and exit. =back =cut =head1 DESCRIPTION xen-delete-image is a simple script which allows you to delete Xen instances which have previously been created by xen-create-image. You must be root to run this script as it removes the Xen configuration file from /etc/xen and potentially removes LVM and EVMS volumes. (When invoked with the '--test' flag the script will continue running, but will fail to remove anything which the user does not have permission to delete.) =cut =head1 LOOPBACK EXAMPLE Assuming that you have three images 'foo', 'bar', and 'baz', stored beneath /home/xen the first two may be deleted via: xen-delete-image --dir=/home/xen foo bar You may also delete them by running: xen-delete-image --dir=/home/xen --hostname=foo --hostname=bar (The matching Xen configuration files beneath /etc/xen will also be removed.) =cut =head1 LVM EXAMPLE Assuming that you have the volume group 'skx-vol' containing three Xen instances 'foo', 'bar', and 'baz' the first two may be deleted via: xen-delete-image --lvm=skx-vol foo bar This will remove the volumes 'foo-disk', 'foo-swap', 'bar-disk', and 'bar-swap'. Note that if the images were created with "--noswap" then the swap volumes will not be present, so will not need to be deleted. The Xen configuration files will also be removed from beneath /etc/xen. =cut =head1 EVMS EXAMPLE Assuming that you have the container 'mycontainer' containing three Xen instances 'foo', 'bar', and 'baz' the first two may be deleted via: xen-delete-image --evms=lvm2/mycontainer --hostname=foo --hostname=bar This will remove the volumes 'foo-disk', 'foo-swap', 'bar-disk', and 'bar-swap'. Note that if the images were created with "--noswap" then the swap volumes will not be present, so will not need to be deleted. The Xen configuration files will also be removed. =cut =head1 AUTHORS Steve Kemp, http://www.steve.org.uk/ Axel Beckert, http://noone.org/abe/ Stéphane Jourdois =cut =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 English; use Getopt::Long; use Pod::Usage; use File::Path; use Xen::Tools::Common; # # 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 file. # my %CONFIG; # # Release number. # my $RELEASE = '4.4~dev'; # # Find xen toolstack command # $CONFIG{ 'xm' } = findXenToolstack(); # # Read the global configuration file if it exists. # if ( -e "/etc/xen-tools/xen-tools.conf" ) { readConfigurationFile("/etc/xen-tools/xen-tools.conf", \%CONFIG); } # # Parse command line arguments, these override the values from the # configuration file. # parseCommandLineArguments(); # # Check that we got valid arguments. # checkArguments(); # # Abort if non-root user. # if ( ( !$CONFIG{ 'test' } ) && ( $EFFECTIVE_USER_ID != 0 ) ) { print < 2 ) if $MANUAL; if ($VERSION) { print "xen-delete-image release $RELEASE\n"; exit; } } =begin doc Check that we received the arguments we expected. =end doc =cut sub checkArguments { # # When testing we only care about loopback images, not disk images. # if ( $CONFIG{ 'test' } ) { $CONFIG{ 'lvm' } = undef; $CONFIG{ 'evms' } = undef; } # # Make sure we got one and only one installation method. # my $count = 0; foreach my $type (qw/dir lvm evms/) { $count += 1 if defined( $CONFIG{ $type } ); } # # Show a decent error for when either zero or more than one options # were selected. # if ( $count != 1 ) { print "Please select one and only one of the installation methods to delete the DomU:\n"; print " --dir\n"; print " --evms\n"; print " --lvm\n"; exit; } } =begin doc Delete the named image, and the corresponding configuration file from /etc/xen. =end doc =cut sub deleteXenImage { my ($hostname) = (@_); # # Collect the names of files to delete. # my @delete; # # Delete the Xen auto-start file if it exists. # if ( -e "/etc/xen/auto/$hostname.cfg" ) { push( @delete, "/etc/xen/auto/$hostname.cfg" ); } # # Delete the Xen configuration file if it exists. # if ( -e "/etc/xen/$hostname.cfg" ) { push( @delete, "/etc/xen/$hostname.cfg" ); } # # If we're working on disk images remove them. # foreach my $file (@delete) { if ( -e $file ) { if ($CONFIG{ 'dry-run' }) { print "Would delete: $file\n"; } else { print "Deleting: $file\n"; unlink($file); } } else { print "Ignoring missing file: $file\n"; } } if ( defined( $CONFIG{ 'dir' } ) ) { my $prefix = $CONFIG{ 'dir' } . "/domains/"; # # Now remove the directory. # if ( -d $prefix . $hostname ) { if ($CONFIG{ 'dry-run' }) { print "Would delete: $prefix$hostname\n"; } else { print "Removing: " . $prefix . $hostname . "\n"; rmtree( $prefix . $hostname ); } } } elsif ( defined( $CONFIG{ 'lvm' } ) ) { # # LVM volumes # # # TODO: Check we're not mounted. # if ( -e "/dev/$CONFIG{'lvm'}/$hostname-swap" ) { if ($CONFIG{ 'dry-run' }) { print "Would remove LVM swap volume /dev/$CONFIG{'lvm'}/$hostname-swap\n"; } else { print "Removing swap volume\n"; runCommand("lvremove /dev/$CONFIG{'lvm'}/$hostname-swap --force", \%CONFIG); } } if ( -e "/dev/$CONFIG{'lvm'}/$hostname-disk" ) { if ($CONFIG{ 'dry-run' }) { print "Would remove LVM disk volume /dev/$CONFIG{'lvm'}/$hostname-disk\n"; } else { print "Removing LVM disk volume\n"; runCommand("lvremove /dev/$CONFIG{'lvm'}/$hostname-disk --force", \%CONFIG); } } } elsif ( defined( $CONFIG{ 'evms' } ) ) { # # EVMS volumes # # # TODO: Check we're not mounted. # if ( -e "/dev/evms/$hostname-swap" ) { if ($CONFIG{ 'dry-run' }) { print "Would remove EVMS swap volume: /dev/evms/$hostname-swap\n"; print "Would remove EVMS swap volume: $CONFIG{'evms'}/$hostname-swap\n"; } else { print "Removing EVMS swap volume\n"; runCommand("echo Delete : /dev/evms/$hostname-swap | evms", \%CONFIG); runCommand("echo Delete : $CONFIG{'evms'}/$hostname-swap | evms", \%CONFIG); } } if ( -e "/dev/evms/$hostname-disk" ) { if ($CONFIG{ 'dry-run' }) { print "Would remove EVMS disk volume: /dev/evms/$hostname-swap\n"; print "Would remove EVMS disk volume: $CONFIG{'evms'}/$hostname-swap\n"; } else { print "Removing EVMS disk volume\n"; runCommand("echo Delete : /dev/evms/$hostname-disk | evms", \%CONFIG); runCommand("echo Delete : $CONFIG{'evms'}/$hostname-disk | evms", \%CONFIG); } } } else { print "Error: No installation type specified\n"; print "Can't happen!\n"; print "Hostname : $hostname\n"; exit 127; } }