2005-12-17 14:21:36 by steve
Initial import.
This commit is contained in:
parent
df2ff282c9
commit
89e2c70498
483
xen-create-image
Executable file
483
xen-create-image
Executable file
@ -0,0 +1,483 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Create a new Xen instances containing an installation of Debian
|
||||
#
|
||||
# This is a reasonably simple script which is more of a cheap hack
|
||||
# than a production tool, however it does appear to work nicely for
|
||||
# my own uses.
|
||||
#
|
||||
# The output of this script will be two files for each new instance:
|
||||
#
|
||||
# 1. One 2Gb file for the installations primary disk image.
|
||||
# 2. One 128Mb file for the images swap partition.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# ./xen-create-image --hostname='vm03' --dir=/home/zen \
|
||||
# --ip=192.168.1.93 --gateway=192.168.1.1 \
|
||||
# --network=192.168.1.0 --mask=255.255.255.0 \
|
||||
#
|
||||
# The initial two arguments '--hostname' and '--dir' are mandatory,
|
||||
# and control the hostname and output directory respectively. Other
|
||||
# parameters are all network based, either give the list as shown above
|
||||
# or use the '--dhcp' option to setup the host with a DHCP allocated
|
||||
# IP address.
|
||||
#
|
||||
# 'dir' is used to create the output disk images which are referenced
|
||||
# in the Xen configuration file. They will be created as:
|
||||
#
|
||||
#
|
||||
# $dir/domains/
|
||||
# $dir/domains/$hostname/disk.img
|
||||
# $dir/domains/$hostname/swap.img
|
||||
#
|
||||
# The '/domains/' subdirectory, and sub-subdirectory named after the
|
||||
# hostname will be created if necessary.
|
||||
#
|
||||
# Basic setup with your hosts file, resolv.conf, etc works just fine.
|
||||
#
|
||||
# The image will also have an OpenSSH server installed upon it, and
|
||||
# an appropriate /etc/inittab file created.
|
||||
#
|
||||
# You are *strongly* advised to chroot() into the new instance once
|
||||
# it has been setup to prune the users in the /etc/passwd file which
|
||||
# will be copied from your hosts system.
|
||||
#
|
||||
#
|
||||
# Steve
|
||||
# --
|
||||
# http://www.steve.org.uk/
|
||||
#
|
||||
# $Id: xen-create-image,v 1.1 2005-12-17 14:21:36 steve Exp $
|
||||
#
|
||||
|
||||
use strict;
|
||||
use File::Copy;
|
||||
use File::Temp qw/ tempdir /;
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
#
|
||||
# Options set on the command line.
|
||||
#
|
||||
my $HOSTNAME; # Mandatory.
|
||||
my $DIR; # Mandatory.
|
||||
|
||||
|
||||
#
|
||||
# Either *all* the relevent networking options must be setup, or
|
||||
# DHCP must be selected.
|
||||
#
|
||||
#
|
||||
my $IP; # set with '--ip=dd.dd.dd.dd'
|
||||
my $GATEWAY; # set with '--gateway=dd.dd.dd.dd'
|
||||
my $NETMASK="255.255.255.0"; # set with '--mask=dd.dd.dd.dd'
|
||||
my $BROADCAST="192.168.1.255"; # set with '--broadcase=ddd.dd.dd.d'
|
||||
my $NETWORK="192.168.1.0"; # set with '--network=dd.dd.dd.dd'
|
||||
my $DHCP=0; # This setting overides the other options
|
||||
|
||||
#
|
||||
# Parse options.
|
||||
#
|
||||
GetOptions(
|
||||
"hostname=s", \$HOSTNAME,
|
||||
"ip=s", \$IP,
|
||||
"gateway=s", \$GATEWAY,
|
||||
"mask=s", \$NETMASK,
|
||||
"broadcast=s", \$BROADCAST,
|
||||
"network=s", \$NETWORK,
|
||||
"dir=s", \$DIR,
|
||||
"dhcp", \$DHCP
|
||||
);
|
||||
|
||||
|
||||
#
|
||||
# Check that the arguments the user has supplied are both
|
||||
# valid, and complete.
|
||||
#
|
||||
checkArguments();
|
||||
|
||||
|
||||
|
||||
#
|
||||
# If the output directories don't exist then create them.
|
||||
#
|
||||
if ( ! -d $DIR . "/domains/" )
|
||||
{
|
||||
mkdir $DIR . '/domains', 0777
|
||||
|| die "Cannot create $DIR/domains - $!";
|
||||
}
|
||||
if ( ! -d $DIR . "/domains/" . $HOSTNAME )
|
||||
{
|
||||
mkdir $DIR. '/domains/' . $HOSTNAME, 0777
|
||||
|| die "Cannot create $DIR/domains/$HOSTNAME - $!" ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#
|
||||
# The two images we'll use, one for the disk image, one for swap.
|
||||
#
|
||||
my $image = $DIR . '/domains/' . $HOSTNAME . "/disk.img" ;
|
||||
my $swap = $DIR . '/domains/' . $HOSTNAME . "/swap.img" ;
|
||||
|
||||
#
|
||||
# Create swapfile and initialise it.
|
||||
#
|
||||
print "Creating swapfile : $swap\n";
|
||||
`/bin/dd if=/dev/zero of=$swap bs=1024k count=128 >/dev/null 2>/dev/null`;
|
||||
print "Initializing swap file\n";
|
||||
`/sbin/mkswap $swap`;
|
||||
print "Done\n";
|
||||
|
||||
#
|
||||
# Create disk file and initialise it.
|
||||
#
|
||||
print "Creating disk image: $image\n";
|
||||
`/bin/dd if=/dev/zero of=$image bs=2M count=1 seek=1024 >/dev/null 2>/dev/null`;
|
||||
print "Creating EXT3 filesystem\n";
|
||||
`/sbin/mkfs.ext3 -F $image`;
|
||||
print "Done\n";
|
||||
|
||||
|
||||
#
|
||||
# Now mount the image, in a secure temporary location.
|
||||
#
|
||||
my $dir = tempdir( CLEANUP => 1 );
|
||||
`mount -t ext3 -o loop $image $dir`;
|
||||
|
||||
#
|
||||
# Test that the mount worked
|
||||
#
|
||||
if ( ! -d $dir . "/lost+found" )
|
||||
{
|
||||
print "Something went wrong trying to mount the new filesystem\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
#
|
||||
# Install the base system.
|
||||
#
|
||||
print "Running debootstrap to install the system. This will take a while!\n";
|
||||
`debootstrap --arch i386 sarge $dir http://ftp.us.debian.org/debian`;
|
||||
print "Done\n";
|
||||
|
||||
#
|
||||
# If the debootstrap failed then we'll setup the output directories
|
||||
# for the configuration files here.
|
||||
#
|
||||
`mkdir -p $dir/etc/apt`;
|
||||
`mkdir -p $dir/etc/network`;
|
||||
|
||||
#
|
||||
# OK now we can do the basic setup.
|
||||
#
|
||||
print "Setting up APT sources .. ";
|
||||
open( APT, ">", $dir . "/etc/apt/sources.list" );
|
||||
print APT<<E_O_APT;
|
||||
#
|
||||
# /etc/apt/sources.list
|
||||
#
|
||||
|
||||
|
||||
# Stable
|
||||
deb http://http.us.debian.org/debian sarge main contrib non-free
|
||||
deb-src http://http.us.debian.org/debian sarge main contrib non-free
|
||||
|
||||
#
|
||||
# Security updates
|
||||
#
|
||||
deb http://security.debian.org/ stable/updates main contrib non-free
|
||||
deb-src http://security.debian.org/ stable/updates main contrib non-free
|
||||
|
||||
|
||||
E_O_APT
|
||||
close( APT );
|
||||
|
||||
print "Done\n";
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Copy some files from the host system, after setting up the hostname.
|
||||
#
|
||||
#
|
||||
`echo '$HOSTNAME' > $dir/etc/hostname`;
|
||||
|
||||
my @hostFiles = ( "/etc/resolv.conf",
|
||||
"/etc/hosts",
|
||||
"/etc/passwd",
|
||||
"/etc/group",
|
||||
"/etc/shadow",
|
||||
"/etc/gshadow" );
|
||||
|
||||
foreach my $file ( @hostFiles )
|
||||
{
|
||||
File::Copy::cp( $file, $dir . "/etc" );
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Disable TLS
|
||||
#
|
||||
if ( -d $dir . "/lib/tls" )
|
||||
{
|
||||
`mv $dir/lib/tls $dir/lib/tls.disabled`;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Now setup the IP address
|
||||
#
|
||||
print "Setting up IP address .. ";
|
||||
open( IP, ">", $dir . "/etc/network/interfaces" );
|
||||
print IP<<E_O_IP;
|
||||
# This file describes the network interfaces available on your system
|
||||
# and how to activate them. For more information, see interfaces(5).
|
||||
|
||||
# The loopback network interface
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
# The primary network interface
|
||||
auto eth0
|
||||
E_O_IP
|
||||
|
||||
if ( $DHCP )
|
||||
{
|
||||
print IP "iface eth0 dhcp\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
print IP <<E_O_STATIC;
|
||||
iface eth0 inet static
|
||||
address $IP
|
||||
gateway $GATEWAY
|
||||
netmask $NETMASK
|
||||
network $NETWORK
|
||||
broadcast $BROADCAST
|
||||
E_O_STATIC
|
||||
}
|
||||
|
||||
close( IP );
|
||||
|
||||
print "Done\n";
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Now setup the fstab
|
||||
#
|
||||
print "Setting up /etc/fstab .. ";
|
||||
open( TAB, ">", $dir . "/etc/fstab" );
|
||||
print TAB<<E_O_TAB;
|
||||
/dev/sda1 / ext3 errors=remount-ro 0 1
|
||||
/dev/sda2 none swap sw 0 0
|
||||
proc /proc proc defaults 0 0
|
||||
E_O_TAB
|
||||
close( TAB );
|
||||
|
||||
print "Done\n";
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Install OpenSSH
|
||||
#
|
||||
installOpenSSH();
|
||||
|
||||
#
|
||||
# Fixup Inittab file
|
||||
#
|
||||
fixupInittab();
|
||||
|
||||
|
||||
|
||||
#
|
||||
# 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/$HOSTNAME.cfg" );
|
||||
print XEN<<E_O_XEN;
|
||||
kernel = "/boot/vmlinuz-2.6.12-xenU"
|
||||
memory = 96
|
||||
name = "$HOSTNAME"
|
||||
disk = [ 'file:$image,sda1,w','file:$swap,sda2,w' ]
|
||||
root = "/dev/sda1 ro"
|
||||
E_O_XEN
|
||||
if ( $DHCP )
|
||||
{
|
||||
print XEN "dhcp=\"dhcp\"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
print XEN "#dhcp=\"dhcp\"\n";
|
||||
}
|
||||
close( XEN );
|
||||
|
||||
print "Done\n";
|
||||
|
||||
|
||||
#
|
||||
# Give status message
|
||||
#
|
||||
print <<EOEND;
|
||||
|
||||
To finish the setup of your new host $HOSTNAME please run:
|
||||
|
||||
mkdir /mnt/tmp
|
||||
mount -t ext3 -o loop $image /mnt/tmp
|
||||
|
||||
chroot /mnt/tmp /bin/bash
|
||||
|
||||
# Get security upgrades.
|
||||
apt-get upgrade
|
||||
|
||||
# setup passwords, etc.
|
||||
passwd root
|
||||
|
||||
# Cleanup.
|
||||
exit
|
||||
umount /mnt/tmp
|
||||
|
||||
Once completed you may start your new instance of Xen with:
|
||||
|
||||
xm create $HOSTNAME.cfg -c
|
||||
|
||||
EOEND
|
||||
|
||||
|
||||
|
||||
|
||||
=head2 checkArguments
|
||||
|
||||
Check that the arguments the user has specified are complete and
|
||||
make sense.
|
||||
|
||||
=cut
|
||||
|
||||
sub checkArguments
|
||||
{
|
||||
|
||||
if (!defined( $HOSTNAME ) )
|
||||
{
|
||||
print<<EOF
|
||||
|
||||
You should set a hostname with '--hostname=foo'.
|
||||
|
||||
This option is required.
|
||||
EOF
|
||||
;
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if (!defined( $DIR ) )
|
||||
{
|
||||
print<<EOF
|
||||
|
||||
You should set an output directory with '--dir=/my/path'.
|
||||
|
||||
This option is required. Subdirectories will be created
|
||||
beneath the directory you name.
|
||||
|
||||
EOF
|
||||
;
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Make sure the directory exists.
|
||||
#
|
||||
if ( ! -d $DIR )
|
||||
{
|
||||
print "Output directory '$DIR' doesn't exist\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Only one of DHCP / IP is required.
|
||||
#
|
||||
if ( $DHCP && $IP )
|
||||
{
|
||||
print "You've chosen both DHCP and an IP address.\n";
|
||||
print "Only one is supported\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( $DHCP )
|
||||
{
|
||||
$GATEWAY="";
|
||||
$NETMASK="";
|
||||
$BROADCAST="";
|
||||
$IP="";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
=head2 installOpenSSH
|
||||
|
||||
Install OpenSSH upon the virtual instance.
|
||||
|
||||
=cut
|
||||
|
||||
sub installOpenSSH
|
||||
{
|
||||
`chroot $dir /usr/bin/apt-get update`;
|
||||
`DEBIAN_FRONTEND=noninteractive chroot $dir /usr/bin/apt-get --yes --force-yes install ssh`;
|
||||
`chroot $dir /etc/init.d/ssh stop`;
|
||||
}
|
||||
|
||||
|
||||
=head2 fixupInittab
|
||||
|
||||
Copy the host systems /etc/inittab to the virtual installation
|
||||
making a couple of minor changes:
|
||||
|
||||
1. Setup the first console to be "Linux".
|
||||
2. Disable all virtual consoles.
|
||||
|
||||
=cut
|
||||
|
||||
sub fixupInittab
|
||||
{
|
||||
my @init;
|
||||
open( INITTAB, "<", "/etc/inittab" );
|
||||
foreach my $line ( <INITTAB> )
|
||||
{
|
||||
chomp $line;
|
||||
if ( $line =~ /:respawn:/ )
|
||||
{
|
||||
if ( $line =~ /^1/ )
|
||||
{
|
||||
$line = "s0:12345:respawn:/sbin/getty 115200 ttyS0 linux"
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = "#" . $line;
|
||||
}
|
||||
}
|
||||
push @init, $line;
|
||||
}
|
||||
close( INITTAB );
|
||||
|
||||
|
||||
open( OUTPUT, ">", "$dir/etc/inittab" );
|
||||
foreach my $line ( @init )
|
||||
{
|
||||
print OUTPUT $line . "\n";
|
||||
}
|
||||
close( OUTPUT )
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user