#!/usr/bin/perl
#
# (C) Copyright IBM Corp. 2004
#
# This program is free software;  you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY;  without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
# the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program;  if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# LVM2 script for testing container creates and deletes.
#
# Test1: Create a container with one PV and default PE size.
# Test2: Create a container with one PV and the minimum PE size.
# Test3: Create a container with one PV and a larger PE size.
# Test4: Create a container with one PV and PE size smaller than the minimum.
#        This should cause the PE size to be automatically rounded up to the
#        minimum.
# Test5: Create a container with one PV and PE size too large for the PV. This
#        should cause the create to fail.
# Test6: Create a container with a PV that's already consumed by another
#        container. This should fail.
# Test7: Create a container with several PVs.
# Test8: Remove all containers created thus far.

use strict;
use warnings;

use Evms::Common;
use Evms::Log;
use Evms::Object;
use Evms::Dos;
use Evms::Lvm2;

# Setup
# Create 10 segments to test with.
sub Setup
{
	my $disk = $_[0];
	my $rc;

	log_info("Create 10 DOS segments.\n");

	$rc = create_dos_segments($disk, 10, "500MB");

	log_info(($rc ? "Failed" : "Success") . "\n\n");
	return $rc;
}

# Test1
# Create a container with one PV and default PE size.
sub Test1
{
	my $disk = $_[0];
	my $name = "Cygnus";
	my $pv = $disk . "5";
	my %options;
	my @output;
	my $rc;

	$options{"name"} = $name;

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   one PV ($pv), default PE size.\n");

	$rc = create_lvm2_container(\%options, $pv);
	if ($rc) {
		log_error("Error creating container $name.\n");
		goto out;
	}

	log_info("2. Verifying creation of container $name.\n");

	@output = query_lvm2_container($name);
	if (!@output) {
		log_error("Error querying info for container $name.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
	return $rc;
}

# Test2
# Create a container with one PV and the minimum PE size.
sub Test2
{
	my $disk = $_[0];
	my $name = "Apollo";
	my $pv = $disk . "6";
	my @output;
	my %options;
	my $rc;

	$options{"name"} = $name;
	$options{"extent_size"} = "8KB";

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   one PV ($pv), minimum PE size.\n");

	$rc = create_lvm2_container(\%options, $pv);
	if ($rc) {
		log_error("Error creating container $name\n");
		goto out;
	}

	log_info("2. Verifying creation of container $name.\n");

	@output = query_lvm2_container($name);
	if (!@output) {
		log_error("Error querying info for container $name.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
	return $rc;
}

# Test3
# Create a container with one PV and a larger PE size.
sub Test3
{
	my $disk = $_[0];
	my $name = "Dionysus";
	my $pv = $disk . "7";
	my @output;
	my %options;
	my $rc;

	$options{"name"} = $name;
	$options{"pe_size"} = "128MB";

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   one PV ($pv), large PE size.\n");

	$rc = create_lvm2_container(\%options, $pv);
	if ($rc) {
		log_error("Error creating container $name\n");
		goto out;
	}

	log_info("2. Verifying creation of container $name.\n");

	@output = query_lvm2_container($name);
	if (!@output) {
		log_error("Error querying info for container $name.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
	return $rc;
}

# Test4
# Create a container with one PV and PE size smaller than the minimum. This
# should cause the PE size to be automatically rounded up to the minimum.
sub Test4
{
        my $disk = $_[0];
        my $name = "Syrinx";
        my $pv = $disk . "8";
	my $pe_size;
	my @output;
	my %options;
        my $rc;

	$options{"name"} = $name;
	$options{"extent_size"} = "2KB";

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   one PV ($pv), PE size below minimum.\n");

        $rc = create_lvm2_container(\%options, $pv);
        if ($rc) {
                log_error("Error creating container $name\n");
                goto out;
        }

        log_info("2. Verifying creation of container $name.\n");

        @output = query_lvm2_container($name);
        if (!@output) {
                log_error("Error querying info for container $name.\n");
		$rc = 1;
                goto out;
        }

        log_info("3. Verifying PE size correctly rounded up.\n");

	$pe_size = get_lvm2_container_pe_size($name);
	if ($pe_size < 0) {
                log_error("Error getting PE size for container $name.\n");
		$rc = 1;
		goto out;
	}

	if ($pe_size != 16) {
		log_error("PE size not correctly rounded to minimum.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
        return $rc;
}

# Test5
# Create a container with one PV and PE size too large for the PV. This
# should cause the PE size to be automatically rounded down to the maximum..
sub Test5
{
        my $disk = $_[0];
        my $name = "Bytor";
        my $pv = $disk . "9";
	my $pe_size;
	my %options;
        my @output;
        my $rc;

	$options{"name"} = $name;
	$options{"extent_size"} = "512MB";

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   one PV ($pv), PE size too large for PV.\n");

        $rc = create_lvm2_container(\%options, $pv);
        if ($rc) {
                log_error("Error creating container $name\n");
		goto out;
	}

        log_info("2. Verifying creation of container $name.\n");

        @output = query_lvm2_container($name);
        if (!@output) {
                log_error("Error querying info for container $name.\n");
		$rc = 1;
                goto out;
        }

        log_info("3. Verifying PE size correctly rounded down.\n");

	$pe_size = get_lvm2_container_pe_size($name);
	if ($pe_size < 0) {
                log_error("Error getting PE size for container $name.\n");
		$rc = 1;
		goto out;
	}

	if ($pe_size != (256 * 1024 * 2)) {
		log_error("PE size not correctly rounded to maximum.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
        return $rc;
}

# Test6
# Create a container with a PV that's already consumed by another container.
# This should fail.
sub Test6
{
	my $disk = $_[0];
	my $name = "Lamneth";
        my $pv = $disk . "9";
	my %options;
        my @output;
        my $rc;

	$options{"name"} = $name;

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   PV ($pv) already in use by another container.\n");

        $rc = create_lvm2_container(\%options, $pv);
        if (!$rc) {
                log_error("Error: container $name created anyway.\n");
		$rc = 1;
		goto out;
	}

        log_info("2. Verifying container $name was *not* created.\n");

        @output = query_lvm2_container($name);
	if (@output) {
                log_error("Error: found container $name.\n");
		$rc = 1;
		goto out;
	}

	$rc = 0;

out:
	log_result($rc);
        return $rc;
}

# Test7
# Create a container with several PVs.
sub Test7
{
	my $disk = $_[0];
	my $name = "Xanadu";
	my @pvs = ($disk."10", $disk."11", $disk."12", $disk."13", $disk."14");
	my $pv;
	my %options;
	my @output;
	my $freespace_size;
	my $rc;

	$options{"name"} = $name;

	log_info("Test creating an LVM2 container.\n");

	log_info("1. Creating LVM2 container $name\n");
	log_info("   Several PVs: @pvs\n");

        $rc = create_lvm2_container(\%options, @pvs);
        if ($rc) {
                log_error("Error creating container $name.\n");
		$rc = 1;
		goto out;
	}

        log_info("2. Verifying creation of container $name.\n");

        @output = query_lvm2_container($name);
	if (!@output) {
                log_error("Error querying info for container $name.\n");
		$rc = 1;
		goto out;
	}

	log_info("3. Verifying all PVs consumed by container $name.\n");

	@output = get_lvm2_container_pvs($name);
	if (!@output) {
                log_error("Error querying for pvs in container $name.\n");
		$rc = 1;
		goto out;
	}

	foreach $pv (@pvs) {
		if (!grep(/$pv/, @output)) {
			log_error("Error finding PV $pv in container $name.\n");
			$rc = 1;
			goto out;
		}
	}

	log_info("4. Verifying size of freespace in container $name.\n");

	$freespace_size = get_object_size("lvm2/" . $name . "/Freespace");
	$rc = compare_sectors(size_to_sectors($freespace_size),
			      5 * size_to_sectors("500MB"), 10);
	if ($rc) {
		log_error("Error: freespace size ($freespace_size) does not " .
			  "equal the sum of all PV sizes.\n");
		goto out;
	}

out:
	log_result($rc);
        return $rc;
}

# Test8
# Remove all containers created thus far.
sub Test8
{
	my $disk = $_[0];
	my @names = ("Cygnus", "Apollo", "Dionysus",
		     "Syrinx", "Bytor", "Xanadu");
	my @output;
	my $name;
	my $i = 1;
	my $rc;

	log_info("Test deleting LVM2 containers.\n");

	foreach $name (@names) {
		log_info("$i. Deleting container $name.\n");
		$rc = delete_lvm2_container($name);
		if ($rc) {
			log_error("Error deleting container $name.\n");
			goto out;
		}
		$i++;

		log_info("$i. Verifying removal of container $name.\n");
		@output = query_lvm2_container($name);
		if (@output) {
			log_error("Error: container $name still exists.\n");
			$rc = 1;
			goto out;
		}
		$i++;
	}

out:
	log_result($rc);
        return $rc;
}

MAIN:
{
	my $disk;
	my $rc;

	# Only use the first disk specified.
	$disk = $ARGV[0];
	$disk || die("USAGE: $0 <disk>\n");

	# Check for minimum-sized disk.
	$rc = check_minimum_object_size($disk, "5GB");
	if ($rc) {
		goto finish;
	}

	$rc = Setup($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test1($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test2($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test3($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test4($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test5($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test6($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test7($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test8($disk);
	if ($rc) {
		goto finish;
	}

finish:
}

