#!/usr/bin/perl
 
use Getopt::Std;
use strict;
use Term::Prompt;
use File::Copy;
 
my %OPTS;
 
if ( !getopts("hfL", \%OPTS) or $OPTS{h}) {
    pod2usage(2);
}
 
die "Must run as root, sorry\n" if ($>) != 0;
 
my $LVS;
my $LV = @ARGV[0];
my $VG = $OPTS{g};
 
my %MIRRORS = (
	    gutsy => "http://archive.ubuntu.com/ubuntu",
	    sid => "http://ftp.debian.org",
	   );
 
 
print "using mirror $MIRRORS{$LV} for $LV" if $MIRRORS{$LV} or die "unknown distro";
 
my $mountpoint = "/mnt";
 
if ( ! $VG ) {
    my $i = 0;
    open(my $VGS, "/sbin/lvm vgs|");
    <$VGS>; # skip first line
    while (<$VGS>) {
	$i = $i + 1;
	m/\s+(\S+)\s+/;
	$VG = $1;
    }
    die "please specify your VG via -g" if ($i != 1);
}
 
print "using volume group $VG\n";
my $device = "/dev/$VG/$LV";
 
# check for filesystem mounted...
open (my $MOUNTS, "/proc/mounts");
while (<$MOUNTS>) {
    # example output:
    #/dev/mapper/hermes--vg-gutsy on /mnt type ext3 (rw)
    if (m/^(\S+) (\S+)/) {
 
	die "volumegroup ($1) already mounted" if ("$1" eq "$device");
	die "$mountpoint ($2) is already mounted" if ($2 eq "$mountpoint");
    }
}
 
print "Looking for $LV\n";
open ($LVS, "/sbin/lvm lvs|");
<$LVS>; # skip first line
while (<$LVS>) {
    if (m/\s+($LV)\s+(\S+)/) {
	my $VG = $2;
	my $remove = undef;
	if (! $OPTS{f}) {
	    $remove = prompt ("y", "Logical Volume $LV bfound on this system, remove?", undef, "y");
	} else {
	    $remove = 1;
	}
	if ($remove) {
	    print "removing $device\n";
	    system ("lvm", "lvremove", "-f", "$device") == 0
	    	or die "could not remove $device: $?";
	}
	last;
    }
}
 
my $size = $OPTS{L};
if ( ! $size ) {
    $size = "3G";
}
 
print "creating $device with a size of $size\n";
system("/sbin/lvm", "lvcreate", "-L", "$size", "-n", "$LV", "$VG") == 0
	or die "could not create $LV: $?";
system("/sbin/mkfs", "-t", "ext3", "$device") == 0
	or die "failed to create filesystem: $?";
system("/bin/mount", "$device", "$mountpoint") == 0
	or die "failed to mount filesystem $device on $mountpoint: $?";
 
if (system("/usr/sbin/debootstrap", "$LV", $mountpoint, $MIRRORS{$LV}) != 0) {
    system("/bin/umount", "$mountpoint");
    die "failed to bootstrap system";
}
 
copy("/etc/hosts", "$mountpoint/etc");
copy("/etc/sudoers", "$mountpoint/etc");
 
system("/bin/umount", "$mountpoint") == 0
	or die "failed to umount filesystem: $?";
 
=head1 NAME
 
  create-chroot
 
=head1 SYNOPSIS
 
  create-chroot [-g VG] [-f] [-L size] distname
 
	-g  		name of Volume group if several on this system
	-f		force removal of existing volume group
	-L 		size of the logical volume. defaults to 3GB.
 
	distname	name of the distribution you want to bootstrap
 
=head1 DESCRIPTION
 
B<create-chroot> is a small shell script for creating LVM based chroot
ready for use with schroot. If the distribution already exists, the
existing logical volume will be removed. It checks if a volumegroup
named like the dist you want to install is already on the system. If
there isn't, then it will create a logical volume, make a filesystem and
bootstrap the selected system on it. It then copies the files
C</etc/hosts> and C</etc/sudoers> into it.
 
After setting it up, make sure you have the chroot added correctly to
C</etc/schroot/schroot.conf>.
 
=head1 AUTHOR
 
Reinhard Tartler <siretart@ubuntu.com>