[xen-tools-dev] [PATCH 17/17] xen-delete-image overhaul to fix KNOWN_BUGS.

Stéphane Jourdois sjourdois at gmail.com
Sun Jul 25 14:12:49 CEST 2010


This is a huge patch. Please REALLY test this one before merging.

An overhaul was the only way to fix known bugs.
This makes xen-delete-image NOT COMPATIBLE with previous releases.

This patches does the following things :
 - Read guest configuration file to obtain used disks
   this fixes first known bug, as now every disk is removed ;
 - Add extension option and use it
   this fixes the second known bug ;
 - Add xm option and use it, taken from xen-create-image ;
 - Really simplify arguments, as now logical volumes are read from
   config file ;
 - Take config/arguments defaults/parsing/validation from
   xen-create-image,
   Read supplied config file as xen-create-image does ;
 - Delete all or no files for each hostname,
   Only exception is EVMS Objects when evms container is not provided,
   sorry for that will fix later, but it should not be harmfull ;
 - Automatically detect lvm/evms volumes and delete them appropriately,
   do not delete real physical devices ; THIS NEEDS REVIEW/TESTING !
 - Some not relevant code styling issues ;
 - Remove t/xen-delete-image.t, it causes more problems than it solves.
   It is the only (AFAIK) functionnality test, and those need to be
   (re)written ;

Enjoy, review, and test :-)
---
 KNOWN_BUGS           |   13 -
 TODO                 |    6 +-
 bin/xen-delete-image |  611 +++++++++++++++++++++++++++++---------------------
 t/xen-delete-image.t |   93 --------
 4 files changed, 362 insertions(+), 361 deletions(-)
 delete mode 100644 KNOWN_BUGS
 delete mode 100755 t/xen-delete-image.t

diff --git a/KNOWN_BUGS b/KNOWN_BUGS
deleted file mode 100644
index 4a74830..0000000
--- a/KNOWN_BUGS
+++ /dev/null
@@ -1,13 +0,0 @@
-KNOWN BUGS in xen-tools
-
-Bugs to fix before a 4.2 release
---------------------------------
-
-* xen-delete-image doesn't remove all logical volumes if --partitions is used.
-
-   See the link below for details how to reproduce. Reproducable at
-   least with --lvm. Thanks to Antoine Benkemoun for reporting.
-
-   http://xen-tools.org/pipermail/xen-tools-discuss/2010-May/000757.html
-
-* xen-delete-image ignores extension setting
diff --git a/TODO b/TODO
index 47d9ee7..e643eca 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,6 @@
 TODO
 ====
 
-See KNOWN_BUGS for real bugs.
-
 Minor bugs to fix and features to add before a 4.2 release
 ----------------------------------------------------------
 
@@ -22,6 +20,8 @@ Minor bugs to fix and features to add before a 4.2 release
    Currently no locales are set and this causes several domU errors
    which appear in the domU's logs.
 
+* xen-delete-image should unallocate any used IP addresses.
+
 Maybe for a 4.3 or 5.0 release
 ------------------------------
 
@@ -128,5 +128,3 @@ Stuff from Steve's TODO list / Generic TODOs
 --------------------------------------------
 
 * Write more test cases.
-
-* xen-delete-image should unallocate any used IP addresses.
diff --git a/bin/xen-delete-image b/bin/xen-delete-image
index f0e99f7..f17ac65 100755
--- a/bin/xen-delete-image
+++ b/bin/xen-delete-image
@@ -9,21 +9,18 @@ xen-delete-image - Delete previously created Xen instances.
   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.
-   --lvm      Specify the LVM volume to use.
-   --evms     Specify the EVMS container to use.
+   --help      Show help information.
+   --manual    Read the manual for this script.
+   --version   Show the version information and exit.
+   --verbose   Show diagnostic output.
 
   Specifying hosts:
-   --hostname Specify the image name to delete.
+   --hostname  Specify the image name to delete.
+   --extension Specify the extension of xen guests configuration files.
 
-  Testing options:
-   --test     Don't complain if we're not invoked by root.
+  Misc. options:
+   --evms      evms container.
+   --dry-run   Do nothing.
 
 =cut
 
@@ -32,30 +29,30 @@ xen-delete-image - Delete previously created Xen instances.
 
 =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.
 
+=item B<--verbose>
+Show diagnostic output.
+
+=item B<--hostname>
+Specify the hostname to delete.
+
+=item B<--extension>
+Specify the extension of xen guests configuration files in /etc/xen/.
+Default value: ".cfg"
+
+=item B<--dry-run>
+Show which files would be deleted, but do not delete them.
+
+=item B<--evms>
+Specify the evms container where evms objects are stored.
 
 =back
 
@@ -70,23 +67,19 @@ Show the version number and exit.
   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
+=head1 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
+    xen-delete-image foo bar
 
   You may also delete them by running:
 
-    xen-delete-image --dir=/home/xen --hostname=foo --hostname=bar
+    xen-delete-image --hostname=foo --hostname=bar
 
   (The matching Xen configuration files beneath /etc/xen will also be
  removed.)
@@ -94,42 +87,6 @@ Show the version number and exit.
 =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 AUTHOR
 
  Steve
@@ -175,63 +132,61 @@ my $RELEASE = '4.2beta1';
 
 
 #
-# Read the global configuration file if it exists.
+#  Setup default options.
 #
-if ( -e "/etc/xen-tools/xen-tools.conf" )
-{
-    readConfigurationFile("/etc/xen-tools/xen-tools.conf");
-}
+setupDefaultOptions();
 
 
 #
-#  Parse command line arguments, these override the values from the
-# configuration file.
+#  Read the global configuration file.
 #
-parseCommandLineArguments();
+readConfigurationFile("/etc/xen-tools/xen-tools.conf");
 
 
 #
-#  Check that we got valid arguments.
+#  Parse the command line arguments.
 #
-checkArguments();
+parseCommandLineArguments();
 
 
 #
-#  Abort if non-root user.
+#  If we received an additional configuration file then read it.
 #
-if ( ( !$CONFIG{ 'test' } ) && ( $EFFECTIVE_USER_ID != 0 ) )
+if ( $CONFIG{ 'config' } )
 {
-    print <<E_O_ROOT;
-
-  This script is not running with root privileges, so the configuration
- file(s) beneath /etc/xen will not be removed.
-
-E_O_ROOT
-
-    exit 127;
-}
-
+    my $path = $CONFIG{ 'config' };
 
+    # If not fully-qualified then read from /etc/xen-tools.
+    if ( $path !~ /^[\/]/ )
+    {
+        $path = "/etc/xen-tools/" . $path;
+    }
 
-#
-#  Loop over the supplied arguments, and attempt to delete each
-# image.
-#
-while ( my $name = shift )
-{
-    if ( !xenRunning($name) )
+    # Read the file, if it exists.
+    if ( -e $path )
     {
-        deleteXenImage($name);
+        readConfigurationFile($path);
     }
     else
     {
-        print "Skipping xen guest '$name' - it appears to be running.\n";
+        logprint( "The specified configuration file does not exist: '$path'\n",
+                  "Aborting\n\n" );
+        exit 127;
     }
 }
 
+
+#  Ensure we're started by root at this point.  This is required
+# to make sure we can delete LVM volumes, or carry out other
+# privileged actions.
+#
+testRootUser();
+
+
 #
-#  Also delete any which were specified using the --hostname flag
+#  Delete any specified hosts.
 #
+push @{ $CONFIG{ 'hostname' } }, @ARGV;
 my $hosts = $CONFIG{ 'hostname' };
 foreach my $name (@$hosts)
 {
@@ -327,97 +282,123 @@ sub readConfigurationFile
 }
 
 
-
 =begin doc
 
-  Parse the arguments specified upon the command line.
+  Validate options and do what is necessary with them.
 
 =end doc
 
 =cut
 
-sub parseCommandLineArguments
+sub checkOption
 {
-    my $HELP    = 0;
-    my $MANUAL  = 0;
-    my $VERSION = 0;
-    $CONFIG{ 'dry-run' } = 0;
-
-    #  Parse options.
-    #
-    GetOptions( "dir=s",       \$CONFIG{ 'dir' },
-                "dry-run",     \$CONFIG{ 'dry-run' },
-                "lvm=s",       \$CONFIG{ 'lvm' },
-                "evms=s",      \$CONFIG{ 'evms' },
-                "hostname=s@", \$CONFIG{ 'hostname' },
-                "test",        \$CONFIG{ 'test' },
-                "verbose",     \$CONFIG{ 'verbose' },
-                "help",        \$HELP,
-                "manual",      \$MANUAL,
-                "version",     \$VERSION
-              );
-
-    pod2usage(1) if $HELP;
-    pod2usage( -verbose => 2 ) if $MANUAL;
-
-
-    if ($VERSION)
-    {
-        my $REVISION = '$Revision: 1.41 $';
-
-        if ( $REVISION =~ /1.([0-9.]+) / )
-        {
-            $REVISION = $1;
+    my ($option, $value) = @_;
+
+    # Define argument types
+    my %types = (
+        hostname => {
+            check   => qr/^[a-z0-9][a-z0-9.-]{0,254}$/i,
+            message => "must be a valid hostname.\n",
+        },
+        configFile => {
+            check   => sub { -e $_[0] or -e "/etc/xen-tools/" . $_[0] },
+            message => "must be an existing file.\n",
+        },
+        filename => {
+            check   => qr/^[a-z0-9_.-]*$/,
+            message => "must be a valid filename.\n",
+        },
+    );
+
+    # Define what argument each option accepts.
+    # Arguments for options not listed here will always be accepted.
+    my %optionsTypes = (
+        hostname      => 'hostname',
+        config        => 'configFile',
+        extension     => 'filename',
+    );
+
+    # If given option does not exists in optionsTypes,
+    # we just copy it to %CONFIG.
+    unless ( exists $optionsTypes{ $option } ) {
+        $CONFIG{ $option } = $value;
+    } else { # we validate it before copying
+        my $type = $optionsTypes{ $option };
+
+        # First, check if type exists
+        die unless exists $types{ $type };
+        my $check = $types{ $type }{ 'check' };
+
+        if (
+            (ref $check eq 'Regexp' and $value =~ $check) or
+            (ref $check eq 'CODE' and &$check( $value ) )
+        ) {
+            # Option did validate, copy it
+            $CONFIG{ $option } = $value;
+        } else {
+            # Option did _not_ validate
+            die "ERROR: '$option' argument " . $types{ $type }{ 'message' };
         }
-
-        print "xen-delete-image release $RELEASE - CVS: $REVISION\n";
-        exit;
-
     }
 }
 
 
-
 =begin doc
 
-  Check that we received the arguments we expected.
+  Parse the command line arguments this script was given.
 
 =end doc
 
 =cut
 
-sub checkArguments
+sub parseCommandLineArguments
 {
+    my $HELP    = 0;
+    my $MANUAL  = 0;
+    my $VERSION = 0;
 
     #
-    #  When testing we only care about loopback images, not disk images.
+    #  Parse options.
     #
-    if ( $CONFIG{ 'test' } )
+    if (
+        !GetOptions(
+
+            "hostname=s@", \&checkOption,
+            "dry-run",     \$CONFIG{ 'dry-run' },
+
+            "config=s",     \&checkOption,
+            "extension=s",  \&checkOption,
+            "evms=s",       \&checkOption,
+
+            # Help options
+            "debug",   \$CONFIG{ 'debug' },
+            "help",    \$HELP,
+            "manual",  \$MANUAL,
+            "verbose", \$CONFIG{ 'verbose' },
+            "version", \$VERSION
+        ) )
     {
-        $CONFIG{ 'lvm' }  = undef;
-        $CONFIG{ 'evms' } = undef;
+        exit;
     }
 
-    #
-    #  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 } );
+    if ( $HELP ) {
+        pod2usage(1);
     }
 
-    #
-    #  Show a decent error for when either zero or more than one options
-    # were selected.
-    #
-    if ( $count != 1 )
+    if ( $MANUAL ) {
+        pod2usage( -verbose => 2 );
+    }
+
+    if ($VERSION)
     {
-        print "Please select one and only one of the installation methods:\n";
-        print " --dir\n";
-        print " --evms\n";
-        print " --lvm\n";
-        exit;
+        my $REVISION = '$Revision: 1.192 $';
+        if ( $REVISION =~ /1.([0-9.]+) / )
+        {
+            $REVISION = $1;
+        }
+
+        logprint("xen-create-image release $RELEASE - CVS: $REVISION\n");
+        exit 0;
     }
 }
 
@@ -437,7 +418,7 @@ sub xenRunning
 
     my $running = 0;
 
-    open( CMD, "xm list $hostname 2>/dev/null |" ) or
+    open( CMD, $CONFIG{ 'xm' } . " list $hostname 2>/dev/null |" ) or
       die "Failed to run 'xm list $hostname'";
     while (<CMD>)
     {
@@ -469,132 +450,170 @@ sub deleteXenImage
     my @delete;
 
     #
-    #  Delete the Xen auto-start file if it exists.
+    #  Delete the Xen configuration file if it exists.
     #
-    if ( -e "/etc/xen/auto/$hostname.cfg" )
+    if ( -e "/etc/xen/$hostname" . $CONFIG{ 'extension' } )
     {
-        push( @delete, "/etc/xen/auto/$hostname.cfg" );
+        push( @delete, "/etc/xen/$hostname" . $CONFIG{ 'extension' } );
+    } else {
+        print "$hostname configuration file does not exists. Skipping.\n";
+        return;
     }
 
     #
-    #  Delete the Xen configuration file if it exists.
+    #  Parse xen guest configuration file.
     #
-    if ( -e "/etc/xen/$hostname.cfg" )
-    {
-        push( @delete, "/etc/xen/$hostname.cfg" );
+    my $guestCfg = '';
+    open GUEST, '<', "/etc/xen/$hostname" . $CONFIG{ 'extension' };
+    while (my $line = <GUEST>) {
+        chop $line;
+        $line =~ s/#.*//; # remove comments
+        $guestCfg .= $line;
     }
+    close GUEST;
 
     #
-    #  If we're working on disk images remove them.
+    #  Extract disks config
     #
-    foreach my $file (@delete)
+    my $guestDisks = '';
+    if ( $guestCfg =~ s/.*disk\s*=\s*\[\s*([^\]]*)\s*\].*//s )
     {
-        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";
-        }
+        $guestDisks = $1;
+    }
+    else
+    {
+        print "Could not read disks configuration from $hostname file. " .
+                     "Skipping.\n";
+        return;
     }
 
-
-    if ( defined( $CONFIG{ 'dir' } ) )
+    #
+    #  Split disks
+    #
+    while ( $guestDisks =~ /'((?:phy|file|):(?:[^,']|(?<=\\)[,'])+)[,']/g )
     {
-        my $prefix = $CONFIG{ 'dir' } . "/domains/";
+        my $diskName = $1;
 
-        #
-        #  Now remove the directory.
-        #
-        if ( -d $prefix . $hostname )
+        if ( $CONFIG{ 'verbose' } )
         {
-            if ($CONFIG{ 'dry-run' }) {
-                print "Would delete: $prefix$hostname\n";
-            } else {
-                print "Removing: " . $prefix . $hostname . "\n";
-                rmtree( $prefix . $hostname );
-            }
+            print "Found disk $diskName for $hostname\n";
         }
-    }
-    elsif ( defined( $CONFIG{ 'lvm' } ) )
-    {
 
         #
-        #  LVM volumes
-        #
+        #  If we're working on disk images remove the top directory.
+        # FIXME: only remove it if empty, user could be using this dir
+        # for other guests.
         #
-        #  TODO: Check we're not mounted.
-        #
-
-        if ( -e "/dev/$CONFIG{'lvm'}/$hostname-swap" )
+        if ( $diskName =~ /^file:(.*\/$hostname)\/.+/ )
         {
-            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");
-            }
+            push @delete, $1;
         }
-
-        if ( -e "/dev/$CONFIG{'lvm'}/$hostname-disk" )
+        else
         {
-            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");
-            }
-        }
+            $diskName =~ s/^[f]ile://;
 
+            # Just remove the file itself
+            push @delete, $diskName;
+        }
     }
-    elsif ( defined( $CONFIG{ 'evms' } ) )
+
+    #
+    #  Delete the Xen auto-start file if it exists.
+    #
+    if ( -e "/etc/xen/auto/$hostname" . $CONFIG{ 'extension' } )
     {
+        push( @delete, "/etc/xen/auto/$hostname" . $CONFIG{ 'extension' } );
+    }
 
-        #
-        #  EVMS volumes
-        #
-        #
-        #  TODO: Check we're not mounted.
-        #
+    #
+    #  Effectively delete files.
+    #
+    foreach my $file (@delete)
+    {
+        if ( $file =~ s/^phy:// )
+        {
+            my $realFile = $file;
+            while ( -l $realFile )
+            {
+                $realFile = readlink $realFile;
+            }
 
-        if ( -e "/dev/evms/$hostname-swap" )
+            if ( $realFile =~ m,^/dev/mapper/, )
+            {
+                #
+                #  LVM volumes
+                #
+                #
+                #  TODO: Check we're not mounted.
+                #
+
+                if ($CONFIG{ 'dry-run' }) {
+                    print "Would remove LVM disk volume $file\n";
+                } else {
+                    print "Removing LVM disk volume\n";
+                    runCommand("lvremove $file --force");
+                }
+            }
+            elsif ( $realFile =~ m,^/dev/evms/, )
+            {
+                #
+                #  EVMS volumes
+                #
+                #
+                #  TODO: Check we're not mounted.
+
+                if ($CONFIG{ 'dry-run' }) {
+                    print "Would remove EVMS disk volume: $file\n";
+                } else {
+                    print "Removing EVMS disk volume\n";
+                    runCommand("echo Delete : $file | evms");
+                }
+
+                if ( $CONFIG{ 'evms' } )
+                {
+                    my $evmsObject = $file;
+                    $evmsObject =~ s,^/dev/evms/,$CONFIG{ 'evms' },;
+
+                    if ($CONFIG{ 'dry-run' }) {
+                        print "Would remove EVMS Object: $evmsObject\n";
+                    } else {
+                        print "Removing EVMS Object\n";
+                        runCommand("echo Delete : $evmsObject | evms");
+                    }
+                }
+                else
+                {
+                    print "WARNING: evms container used for $hostname " .
+                          "but not specified. EVMS Object not deleted !\n";
+                }
+            }
+        }
+        elsif ( -d $file )
         {
             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";
+                print "Would delete: $file/\n";
             } else {
-                print "Removing EVMS swap volume\n";
-                runCommand("echo Delete : /dev/evms/$hostname-swap | evms");
-                runCommand("echo Delete : $CONFIG{'evms'}/$hostname-swap | evms");
+                print "Deleting: $file/\n"
+                    if $CONFIG{ 'verbose' };
+                rmtree($file);
             }
         }
-
-        if ( -e "/dev/evms/$hostname-disk" )
+        elsif ( -e $file )
         {
             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";
+                print "Would delete: $file\n";
             } else {
-                print "Removing EVMS disk volume\n";
-                runCommand("echo Delete : /dev/evms/$hostname-disk | evms");
-                runCommand("echo Delete : $CONFIG{'evms'}/$hostname-disk | evms");
+                print "Deleting: $file\n"
+                    if $CONFIG{ 'verbose' };
+                unlink($file);
             }
         }
-
-    }
-    else
-    {
-        print "Error:  No installation type specified\n";
-        print "Can't happen!\n";
-        print "Hostname : $hostname\n";
-        exit 127;
+        else
+        {
+            print "Ignoring missing file: $file\n";
+        }
     }
+
 }
 
 
@@ -659,3 +678,93 @@ sub runCommand
 
     return ($output);
 }
+
+
+=begin doc
+
+  Setup the default options we'd expect into our global configuration hash.
+
+=end doc
+
+=cut
+
+sub setupDefaultOptions
+{
+
+    #
+    # Paths and files.
+    #
+    $CONFIG{ 'dir' }     = '';
+    $CONFIG{ 'xm' }      = findBinary("xm");
+
+    #
+    # Hosts to delete.
+    $CONFIG{ 'hostname' } = [];
+
+    #
+    # Misc. options.
+    #
+
+    $CONFIG{ 'partitionsdir' } = '/etc/xen-tools/partitions.d';
+    $CONFIG{ 'ipfile' }        = '/etc/xen-tools/ips.txt';
+    $CONFIG{ 'output' }        = '/etc/xen';
+    $CONFIG{ 'extension' }     = '.cfg';
+    $CONFIG{ 'dry-run' }       = 0;
+    $CONFIG{ 'evms' }          = '';
+
+}
+
+
+=begin doc
+
+  Make sure this script is being run by a user with UID 0.
+
+=end doc
+
+=cut
+
+sub testRootUser
+{
+    if ( $EFFECTIVE_USER_ID != 0 )
+    {
+        my $err = <<E_O_ROOT;
+
+  In order to use this script you must be running with root privileges.
+
+E_O_ROOT
+
+        logprint($err);
+        exit 127;
+    }
+}
+
+
+=begin doc
+
+  Find the location of the specified binary on the curent user's PATH.
+
+  Return undef if the named binary isn't found.
+
+=end doc
+
+=cut
+
+sub findBinary
+{
+    my ($bin) = (@_);
+
+    # strip any path which might be present.
+    $bin = $2 if ( $bin =~ /(.*)[\/\\](.*)/ );
+
+    foreach my $entry ( split( /:/, $ENV{ 'PATH' } ) )
+    {
+
+        # guess of location.
+        my $guess = $entry . "/" . $bin;
+
+        # return it if it exists and is executable
+        return $guess if ( -e $guess && -x $guess );
+    }
+
+    return undef;
+}
diff --git a/t/xen-delete-image.t b/t/xen-delete-image.t
deleted file mode 100755
index 861a9c0..0000000
--- a/t/xen-delete-image.t
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/perl -w
-#
-#  Test that the xen-delete-image script will delete an images
-# contents correctly.
-#
-# Steve
-# --
-#
-
-
-use strict;
-use Test::More qw( no_plan );
-use File::Temp;
-
-
-#
-#  Create a temporary directory.
-#
-my $dir            = File::Temp::tempdir( CLEANUP => 1 );
-my $domains = $dir . "/domains";
-
-#
-#  Test that we can make the directory.
-#
-ok ( -d $dir, "The temporary directory was created: $dir" );
-
-#
-#  Create the domains directory.
-#
-ok ( ! -d $domains, "The temp directory doesn't have a domains directory." );
-mkdir( $domains, 0777 );
-ok ( -d $domains, "The temp directory now has a domains directory." );
-
-
-#
-#  Generate a random hostname.
-#
-my $hostname = join ( '', map {('a'..'z')[rand 26]} 0..17 );
-ok( ! -d $domains . "/" . $hostname, "The virtual hostname doesnt exist." );
-
-#
-#  Make the hostname directory
-#
-mkdir( $domains . "/" . $hostname, 0777 );
-ok( -d $domains . "/" . $hostname, "The virtual hostname now exists." );
-
-
-#
-#  Create a stub disk image
-#
-open( IMAGE, ">", $domains . "/" . $hostname . "/" . "disk.img" )
-  or warn "Failed to open disk image : $!";
-print IMAGE "Test";
-close( IMAGE );
-
-
-#
-#  Create a stub swap image
-#
-open( IMAGE, ">", $domains . "/" . $hostname . "/" . "swap.img" )
-  or warn "Failed to open swap image : $!";
-print IMAGE "Test";
-close( IMAGE );
-
-
-#
-#  Now we have :
-#
-#  $dir/
-#  $dir/domains/
-#  $dir/domains/$hostname
-#  $dir/domains/$hostname/disk.img
-#  $dir/domains/$hostname/swap.img
-#
-#  So we need to run the deletion script and verify the images
-# are removed correctly.
-#
-`./bin/xen-delete-image --test --dir=$dir $hostname`;
-
-
-#
-#  If the deletion worked our images are gone.
-#
-ok( ! -e $domains . "/" . $hostname . "/" . "disk.img",
-    "Disk image deleted successfully." );
-ok( ! -e $domains . "/" . $hostname . "/" . "swap.img",
-    "Swap image deleted successfully." );
-
-#
-#  And the hostname directory should have gone too.
-#
-ok( ! -d $domains . "/" . $hostname,
-    "The hostname directory was removed" );
-- 
1.7.2



More information about the xen-tools-dev mailing list