From eafc7427c2872fc4143b76e07ecca135178ef029 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 7 Jul 2007 23:49:02 +0000 Subject: [PATCH] 2007-07-07 23:48:08 by steve INITIAL COMMIT: Support for arbitary partitioning systems. Patch from Sascha Kettler. --- AUTHORS | 3 + Makefile | 4 +- bin/xen-create-image | 1049 ++++++++++++++++------------- bin/xt-create-xen-config | 71 +- debian/changelog | 7 + debian/control | 2 +- etc/xm.tmpl | 17 +- hooks/centos4/90-make-fstab | 72 +- hooks/dapper/80-install-modules | 11 +- hooks/dapper/90-make-fstab | 75 +-- hooks/debian/15-disable-hwclock | 15 +- hooks/debian/55-create-dev | 8 + hooks/debian/80-install-modules | 11 +- hooks/debian/90-make-fstab | 76 +-- hooks/debian/95-configure-locales | 5 - hooks/edgy/80-install-modules | 11 +- hooks/edgy/90-make-fstab | 75 +-- hooks/fedora/90-make-fstab | 76 +-- hooks/gentoo/90-make-fstab | 65 +- misc/xen-tools | 9 +- partitions/sample-server | 45 ++ tests/modules.t | 4 + tests/xt-create-xen-config.t | 6 +- 23 files changed, 997 insertions(+), 720 deletions(-) create mode 100644 partitions/sample-server diff --git a/AUTHORS b/AUTHORS index 45ae149..7c2ea48 100644 --- a/AUTHORS +++ b/AUTHORS @@ -32,6 +32,9 @@ Contributions Kirk Ismay - Added hook for automatic CFEngine installation. + Sascha Kettler + - Implemented support for arbitary partitioning schemes. + Eric Lemoine - Improved binary detection and good suggestions. - Better portability for non-bash shells. diff --git a/Makefile b/Makefile index c951aff..e93569d 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ # -- # http://www.steve.org.uk/ # -# $Id: Makefile,v 1.105 2007-06-16 13:44:37 steve Exp $ +# $Id: Makefile,v 1.106 2007-07-07 23:48:08 steve Exp $ # @@ -100,9 +100,11 @@ install-etc: -if [ -d ${prefix}/etc/xen-tools/hook.d ]; then mv ${prefix}/etc/xen-tools/hook.d/ ${prefix}/etc/xen-tools/hook.d.obsolete ; fi -mkdir -p ${prefix}/etc/xen-tools/skel/ -mkdir -p ${prefix}/etc/xen-tools/role.d/ + -mkdir -p ${prefix}/etc/xen-tools/partitions.d/ cp etc/xen-tools.conf ${prefix}/etc/xen-tools/ cp etc/xm.tmpl ${prefix}/etc/xen-tools/ cp etc/xm-nfs.tmpl ${prefix}/etc/xen-tools/ + cp partitions/*-* ${prefix}/etc/xen-tools/partitions.d/ -mkdir -p ${prefix}/etc/bash_completion.d cp misc/xen-tools ${prefix}/etc/bash_completion.d/ cp misc/xm ${prefix}/etc/bash_completion.d/ diff --git a/bin/xen-create-image b/bin/xen-create-image index c5b0878..0064f1f 100755 --- a/bin/xen-create-image +++ b/bin/xen-create-image @@ -43,7 +43,7 @@ xen-create-image - Easily create new Xen instances with networking and OpenSSH. those which are liable to be used by the new invocation. --fs Specify the filesystem type to use for the new guest. - Valid choices are 'ext3', 'reiserfs', or 'xfs'. + Valid choices are 'ext2', 'ext3', 'reiserfs', or 'xfs'. --image Specify whether to create "sparse" or "full" disk images. Full images are mandatory when using LVM, so this setting @@ -61,10 +61,18 @@ xen-create-image - Easily create new Xen instances with networking and OpenSSH. --memory Setup the amount of memory allocated to the new instance. + --modules Set the path to the kernel modules to use for domU. + If modules are specified they must exist. + --install Specify whether to install the guest system or not. --hooks Specify whether to run hooks after the image is created. + --partitions Use a specific partition layout configuration file. + Not supported with the image-dev and swap-dev options. + Parameters fs, size, swap and noswap are ignored when + using this option. + --passwd Ask for a root password during setup. NOTE: This is done interactively. @@ -563,7 +571,7 @@ Install an X11 server, using VNC and XDM -- http://www.steve.org.uk/ - $Id: xen-create-image,v 1.159 2007-06-29 11:52:19 steve Exp $ + $Id: xen-create-image,v 1.160 2007-07-07 23:48:09 steve Exp $ =cut @@ -580,6 +588,7 @@ The LICENSE file contains the full text of the license. use strict; +use Config::IniFiles; use English; use Env; use File::Path qw/ mkpath /; @@ -594,6 +603,11 @@ use Pod::Usage; # my %CONFIG; +# +# Partition layout information values read from the partitions file. +# +my @PARTITIONS = undef; + # # Global variable containing the temporary file where our image # is mounted for installation purposes. @@ -624,7 +638,7 @@ my $RELEASE = '3.5'; testXenConfig(); -exit; + @@ -722,9 +736,9 @@ checkBinariesPresent(); # -# Show a summery of what we're going to do. +# Show a summary of what we're going to do. # -showSummery(); +showSummary(); @@ -754,7 +768,7 @@ elsif ( $CONFIG{'lvm'} ) elsif ( $CONFIG{'evms'} ) { # - # Create our evms partitions. + # Create our EVMS partitions. # createEVMSBits(); } @@ -796,7 +810,7 @@ exportEnvironment(); # a binary name that is reasonably likely to exist under any # distribution of GNU/Linux. # -if ( ! $CONFIG{'install'} ) +if ( $CONFIG{'install'} ) { # # Install the system. @@ -1086,34 +1100,37 @@ sub setupDefaultOptions # # Paths and files. # - $CONFIG{'dir'} = ''; - $CONFIG{'xm'} = findBinary( "xm" ); - $CONFIG{'kernel'} = ''; - $CONFIG{'initrd'} = ''; + $CONFIG{'dir'} = ''; + $CONFIG{'xm'} = findBinary( "xm" ); + $CONFIG{'kernel'} = ''; + $CONFIG{'modules'} = ''; + $CONFIG{'initrd'} = ''; # # Sizing options. # - $CONFIG{'memory'} = '96Mb'; - $CONFIG{'size'} = '2000Mb'; - $CONFIG{'swap'} = '128M'; - $CONFIG{'cache'} = 'yes'; - $CONFIG{'image'} = 'sparse'; + $CONFIG{'memory'} = '96Mb'; + $CONFIG{'size'} = '2000Mb'; + $CONFIG{'swap'} = '128M'; + $CONFIG{'cache'} = 'yes'; + $CONFIG{'image'} = 'sparse'; # # Misc. options. # - $CONFIG{'mirror'} = 'http://ftp.us.debian.org/debian'; - $CONFIG{'arch'} = ''; - $CONFIG{'dist'} = 'sarge'; - $CONFIG{'fs'} = 'ext3'; - $CONFIG{'force'} = 0; - $CONFIG{'install'} = 1; - $CONFIG{'hooks'} = 1; - $CONFIG{'pid'} = 0; - $CONFIG{'template'} = ''; - $CONFIG{'roledir'} = '/etc/xen-tools/role.d'; - $CONFIG{'ipfile'} = '/etc/xen-tools/ips.txt'; + $CONFIG{'mirror'} = 'http://ftp.us.debian.org/debian'; + $CONFIG{'arch'} = ''; + $CONFIG{'dist'} = 'sarge'; + $CONFIG{'fs'} = 'ext3'; + $CONFIG{'force'} = 0; + $CONFIG{'install'} = 1; + $CONFIG{'hooks'} = 1; + $CONFIG{'partitions'} = ''; + $CONFIG{'pid'} = 0; + $CONFIG{'template'} = ''; + $CONFIG{'roledir'} = '/etc/xen-tools/role.d'; + $CONFIG{'partitionsdir'} = '/etc/xen-tools/partitions.d'; + $CONFIG{'ipfile'} = '/etc/xen-tools/ips.txt'; # # Installation method defaults to "debootstrap". @@ -1130,6 +1147,7 @@ sub setupDefaultOptions # filesystem, even if it exists. This script must detect # prior existance itself. # + $CONFIG{'make_fs_ext2'} = 'mkfs.ext2 -F '; $CONFIG{'make_fs_ext3'} = 'mkfs.ext3 -F '; $CONFIG{'make_fs_xfs'} = 'mkfs.xfs -f -d name='; $CONFIG{'make_fs_reiserfs'} = 'mkfs.reiserfs -f -q '; @@ -1140,6 +1158,7 @@ sub setupDefaultOptions # NOTE: Kinda redundent and may go away since '-t auto' should do # the right thing. # + $CONFIG{'mount_fs_ext2'} = '-t ext2'; $CONFIG{'mount_fs_ext3'} = '-t ext3'; $CONFIG{'mount_fs_xfs'} = '-t xfs'; $CONFIG{'mount_fs_reiserfs'} = '-t reiserfs'; @@ -1275,6 +1294,7 @@ sub parseCommandLineArguments "kernel=s", \$CONFIG{'kernel'}, "initrd=s", \$CONFIG{'initrd'}, "mirror=s", \$CONFIG{'mirror'}, + "modules=s", \$CONFIG{'modules'}, "lvm=s", \$install{'lvm'}, "image-dev=s", \$install{'image-dev'}, "swap-dev=s", \$install{'swap-dev'}, @@ -1310,6 +1330,7 @@ sub parseCommandLineArguments "install=i", \$CONFIG{'install'}, "hooks=i", \$CONFIG{'hooks'}, "passwd", \$CONFIG{'passwd'}, + "partitions=s", \$CONFIG{'partitions'}, "role=s", \$CONFIG{'role'}, "role-args=s", \$CONFIG{'role-args'}, "roledir=s", \$CONFIG{'roledir'}, @@ -1331,7 +1352,7 @@ sub parseCommandLineArguments if ( $VERSION ) { - my $REVISION = '$Revision: 1.159 $'; + my $REVISION = '$Revision: 1.160 $'; if ( $REVISION =~ /1.([0-9.]+) / ) { $REVISION = $1; @@ -1352,6 +1373,8 @@ sub parseCommandLineArguments $CONFIG{'evms'} = undef; $CONFIG{'lvm'} = undef; $CONFIG{'image-dev'} = undef; + + populatePartitionsData(); } if ( $install{'evms'} ) { @@ -1359,6 +1382,8 @@ sub parseCommandLineArguments $CONFIG{'evms'} = $install{'evms'}; $CONFIG{'lvm'} = undef; $CONFIG{'image-dev'} = undef; + + populatePartitionsData(); } if ( $install{'lvm'} ) { @@ -1366,6 +1391,8 @@ sub parseCommandLineArguments $CONFIG{'evms'} = undef; $CONFIG{'lvm'} = $install{'lvm'}; $CONFIG{'image-dev'} = undef; + + populatePartitionsData(); } if ( $install{'image-dev'} ) { @@ -1584,12 +1611,58 @@ EOF } } + + # + # If we've got a partitions directory specified then it must exist. + # + if ( defined( $CONFIG{'partitionsdir'} ) && length( $CONFIG{'partitionsdir'} ) ) + { + if ( ! -d $CONFIG{'partitionsdir'} ) + { + logprint( "The specified partitions directory '$CONFIG{'partitionsdir'}' does not exist\n" ); + exit 1; + } + } + + + # + # Make sure that any specified partitions file exists. + # + if ( ( defined( $CONFIG{'partitions'} ) ) && + ( length( $CONFIG{'partitions'} ) ) ) + { + if ( ! ( $CONFIG{'partitions'} =~ /\// ) ) + { + $CONFIG{'partitions'} = $CONFIG{'partitionsdir'} . '/' . $CONFIG{'partitions'}; + } + + if ( ! -e $CONFIG{'partitions'} ) + { + logprint( "The specified partitions file, $CONFIG{'partitions'}, does not exist.\n" ); + exit 1; + } + + loadAndCheckPartitionsFile(); + } + if ( $CONFIG{'swap-dev'} && $CONFIG{'noswap'} ) { logprint( "Please choose either swap-dev or noswap, not both!\n" ); exit 1; } + if ( $CONFIG{'swap-dev'} && $CONFIG{'partitions'} ) + { + logprint( "Please choose either swap-dev or partitions, not both!\n" ); + exit 1; + } + + if ( $CONFIG{'image-dev'} && $CONFIG{'partitions'} ) + { + logprint( "Please choose either image-dev or partitions, not both!\n" ); + exit 1; + } + # # The user must choose either DHCP *or* Static IP. not both @@ -1719,13 +1792,177 @@ sub checkBinariesPresent =begin doc - Show the user a summery of what is going to be created for them + Loads a partitions file, checks the syntax and updates the configuration variables with it =end doc =cut -sub showSummery +sub loadAndCheckPartitionsFile +{ + my %partitions; + tie %partitions, 'Config::IniFiles', ( -file => $CONFIG{'partitions'} ); + + @PARTITIONS = (); + + my $name; + my $details; + my $foundroot = 0; + while ( ( $name, $details ) = each %partitions ) + { + if ( ! ( $name =~ /^[a-zA-Z0-9-]+$/ ) ) + { + logprint( "The partition name $name contains invalid characters.\n" ); + logprint( "Only alphanumeric characters and the hyphen are allowed\n" ); + exit 1; + } + + if ( ! ( $details->{'size'} =~ /^[0-9.]+[GgMmKk]b?$/ ) ) + { + logprint( "The size $details->{'size'} of partition $name contains is not recognized.\n" ); + exit 1; + } + + if ( $details->{'type'} eq 'swap' ) + { + push( @PARTITIONS, { 'name' => $name, 'size' => $details->{'size'}, 'type' => 'swap', 'mountpoint' => '', 'options' => '' } ); + } + else + { + if ( ! $CONFIG{ 'make_fs_' . $details->{'type'} } ) + { + logprint( "The type $details->{'type'} of partition $name is not recognized.\n" ); + exit 1; + } + + if ( ! ( $details->{'mountpoint'} =~ /^\/[^: \t\r\n]*$/ ) ) + { + logprint( "The mount point $details->{'mountpoint'} of partition $name is invalid.\n" ); + exit 1; + } + + if ( ! ( $details->{'options'} =~ /^[^: \t\r\n]*$/ ) ) + { + logprint( "The mount options $details->{'options'} of partition $name are invalid.\n" ); + exit 1; + } + + if ( ! $details->{'options'} ) + { + $details->{'options'} = 'defaults'; + } + + if ( $details->{'mountpoint'} eq '/' ) + { + $foundroot = 1; + } + + push( @PARTITIONS, + { + 'name' => $name, + 'size' => $details->{'size'}, + 'type' => $details->{'type'}, + 'mountpoint' => $details->{'mountpoint'}, + 'options' => $details->{'options'} + } + ); + } + } + + if ( ! $foundroot ) + { + logprint( "The root partition was not specified.\n" ); + exit 1; + } + + # + # Sort by length of the mountpoint. + # + # This makes it easy to mount parent folders first + # (e.g. /var before /var/tmp) + # + @PARTITIONS = sort { length $a->{'mountpoint'} cmp length $b->{'mountpoint'} } @PARTITIONS; +} + + + + +=begin doc + + Populates the partition information using the supplied configuration arguments when not using the partitions file + +=end doc + +=cut + +sub populatePartitionsData +{ + @PARTITIONS = (); + + # + # [swap] + # + push( @PARTITIONS, { 'name' => 'swap', + 'size' => $CONFIG{'swap'}, + 'type' => 'swap', + 'mountpoint' => '', + 'options' => '' } ) + unless( $CONFIG{'noswap'} ); + + # + # XFS has different default options. + # + my $options = 'errors=remount-ro'; + $options = 'defaults' if ( $CONFIG{'fs'} eq 'xfs' ); + + # + # [root] + # + push( @PARTITIONS, { 'name' => 'disk', + 'size' => $CONFIG{'size'}, + 'type' => $CONFIG{'fs'}, + 'mountpoint' => '/', + 'options' => $options } ); +} + + + +=begin doc + + Converts the internal partitions array into a text representation suitable for passing to other scripts. + +=end doc + +=cut + +sub exportPartitionsToConfig +{ + $CONFIG{'NUMPARTITIONS'} = $#PARTITIONS + 1; + + my $i; + for ( $i = 0; $i < $CONFIG{'NUMPARTITIONS'}; $i++ ) + { + $CONFIG{'PARTITION' . ( $i + 1 )} = $PARTITIONS[$i]{'name'} . ':' . + $PARTITIONS[$i]{'size'} . ':' . + $PARTITIONS[$i]{'type'} . ':' . + $PARTITIONS[$i]{'mountpoint'} . ':' . + $PARTITIONS[$i]{'options'} . ':' . + $PARTITIONS[$i]{'imagetype'} . ':' . + $PARTITIONS[$i]{'image'}; + } +} + + + +=begin doc + + Show the user a summary of what is going to be created for them + +=end doc + +=cut + +sub showSummary { # # Show the user what to expect. @@ -1734,27 +1971,32 @@ sub showSummery logprint( "--------------------\n" ); logprint( "Hostname : $CONFIG{'hostname'}\n" ); logprint( "Distribution : $CONFIG{'dist'}\n" ); - logprint( "Fileystem Type : $CONFIG{'fs'}\n" ); if ( defined $CONFIG{'image-dev'} ) { - logprint( "Image Device : $CONFIG{'image-dev'}\n" ); + logprint( "Root Device : $CONFIG{'image-dev'}\n" ); } if ( defined $CONFIG{'swap-dev'} ) { logprint( "Swap Device : $CONFIG{'swap-dev'}\n" ); } - logprint( "\nSize Information\n" ); - logprint( "----------------\n" ); + my $info; + my $partcount = 0; - if ( defined $CONFIG{'size'} ) + logprint( "Partitions : " ); + foreach my $partition ( @PARTITIONS ) { - logprint( "Image size : $CONFIG{'size'}\n") ; - } - if ( defined $CONFIG{'swap'} ) - { - logprint( "Swap size : $CONFIG{'swap'}\n" ) unless ( $CONFIG{'noswap' } ); + $info = sprintf('%-15s %-5s (%s)', ($partition->{'type'} ne 'swap') ? $partition->{'mountpoint'} : 'swap', $partition->{'size'}, $partition->{'type'}); + + if ($partcount++) + { + logprint( " $info\n" ); + } + else + { + logprint( "$info\n" ); + } } logprint( "Image type : $CONFIG{'image'}\n" ); @@ -1765,6 +2007,11 @@ sub showSummery logprint( "Kernel path : $CONFIG{'kernel'}\n" ); } + if ( defined( $CONFIG{'modules'} ) && length( $CONFIG{'modules'} ) ) + { + logprint( "Module path : $CONFIG{'modules'}\n" ); + } + if ( defined( $CONFIG{'initrd'} ) && length( $CONFIG{'initrd'} ) ) { logprint( "Initrd path : $CONFIG{'initrd'}\n" ); @@ -1933,12 +2180,6 @@ sub testLoopbackModule sub createLoopbackImages { - # - # The two files we need to test. - # - my $disk = $CONFIG{'dir'} . '/domains/' . $CONFIG{'hostname'} . "/disk.img" ; - my $swap = $CONFIG{'dir'} . '/domains/' . $CONFIG{'hostname'} . "/swap.img" ; - # # Make sure we have the relevant output directory. # @@ -1963,105 +2204,89 @@ sub createLoopbackImages # # Only proceed overwritting if we have --force specified. # - if ( ( -e $disk ) && ! $CONFIG{'force'} ) + if ( ! $CONFIG{'force'} ) { - logprint( "The disk image already exists. Aborting.\n" ); - logprint( "Specify '--force' to overwrite, or remove the following file\n" ); - logprint( $disk . "\n" ); - exit; - } - if ( ( -e $swap ) && ! $CONFIG{'force'} ) - { - logprint( "The swap image already exists. Aborting.\n" ); - logprint( "Specify '--force' to overwrite, or remove the following file\n" ); - logprint( $swap . "\n" ); - exit; - } - - - # - # Modify the sizes to something reasonable - # - my $disk_size = $CONFIG{'size'}; - my $swap_size = $CONFIG{'swap'}; - - # - # Convert Gb -> Mb for the disk image size, and swap size. - # - if ( $disk_size =~ /^(\d+)Gb*$/i ) - { - $disk_size = $1 * 1024 . "M"; - } - if ( $swap_size =~ /^(\d+)Gb*$/i ) - { - $swap_size = $1 * 1024 . "M"; - } - - # - # Final adjustments to sizing. - # - $disk_size =~ s/Mb*$/k/i; - if ( $swap_size =~ /^(\d+)Mb*$/i ) - { - $swap_size = $1; - } - - # - # Use dd to create the swap - # - unless( $CONFIG{'noswap'} ) - { - logprint( "\nCreating swap image: $swap\n" ); - my $swap_cmd = "dd if=/dev/zero of=$swap bs=1024k count=$swap_size"; - runCommand( $swap_cmd ); - logprint( "Done\n" ); - } - - - # - # Use dd to create the disk image. - # - logprint( "\nCreating disk image: $disk\n" ); - my $image_cmd; - if ( $CONFIG{'image'} eq "sparse" ) - { - $CONFIG{'verbose'} && logprint( "Creating sparse image\n" ); - $image_cmd = "dd if=/dev/zero of=$disk bs=$disk_size count=0 seek=1024"; - } - else - { - $CONFIG{'verbose'} && logprint( "Creating full-sized image\n" ); - $image_cmd = "dd if=/dev/zero of=$disk bs=$disk_size count=1024"; - } - - runCommand( $image_cmd ); - logprint( "Done\n" ); - - # - # Make sure the volumes exist. - # - if ( ! -e $swap ) - { - unless( $CONFIG{'noswap'} ) + foreach my $partition ( @PARTITIONS ) { - logprint( "The disk image creation failed to create $swap.\n" ); - logprint( "aborting\n" ); - exit; + my $disk = $CONFIG{'dir'} . '/domains/' . $CONFIG{'hostname'} . '/' . $partition->{'name'} . '.img'; + + if ( -e $disk ) + { + logprint( "The partition image already exists. Aborting.\n" ); + logprint( "Specify '--force' to overwrite, or remove the following file\n" ); + logprint( $disk . "\n" ); + exit; + } } } - if ( ! -e $disk ) - { - logprint( "The disk image creation failed to create $disk.\n" ); - logprint( "aborting\n" ); - exit; - } - # - # Finally create the filesystem + swap - # - createFilesystem( $disk ); - createSwap( $swap ) unless( $CONFIG{'noswap'} ); + foreach my $partition ( @PARTITIONS ) + { + my $disk = $CONFIG{'dir'} . '/domains/' . $CONFIG{'hostname'} . '/' . $partition->{'name'} . '.img'; + + # + # Save the image path to the partitions array + # + $partition->{'imagetype'} = 'file:'; + $partition->{'image'} = $disk; + + # + # Modify the size to something reasonable + # + my $size = $partition->{'size'}; + + # + # Convert Gb -> Mb for the partition image size. + # + if ( $size =~ /^([0-9.]+)Gb*$/i ) + { + $size = $1 * 1024 . "M"; + } + + # + # Final adjustments to sizing. + # + $size =~ s/Mb*$/k/i; + + # + # Use dd to create the partition image. + # + logprint( "\nCreating partition image: $disk\n" ); + my $image_cmd; + if ( $CONFIG{'image'} eq "sparse" ) + { + $CONFIG{'verbose'} && logprint( "Creating sparse image\n" ); + $image_cmd = "dd if=/dev/zero of=$disk bs=$size count=0 seek=1024"; + } + else + { + $CONFIG{'verbose'} && logprint( "Creating full-sized image\n" ); + $image_cmd = "dd if=/dev/zero of=$disk bs=$size count=1024"; + } + + runCommand( $image_cmd ); + logprint( "Done\n" ); + + if ( ! -e $disk ) + { + logprint( "The partition image creation failed to create $disk.\n" ); + logprint( "aborting\n" ); + exit; + } + + # + # Finally create the filesystem / swap + # + if ( $partition->{'type'} eq 'swap' ) + { + createSwap( $disk ); + } + else + { + createFilesystem( $disk, $partition->{'type'} ); + } + } } @@ -2080,18 +2305,10 @@ sub createLoopbackImages sub usePhysicalDevice { - my $phys_img = undef; - my $swap_img = undef; + my $phys_img; + my $swap_img; - if ( defined $CONFIG{'image-dev'} ) - { - $phys_img = $CONFIG{'image-dev'}; - } - else - { - logprint( "No image-dev parameter given. Aborting.\n" ); - exit; - } + @PARTITIONS = (); if ( defined $CONFIG{'swap-dev'} ) { @@ -2103,16 +2320,30 @@ sub usePhysicalDevice logprint( "NOTE: Please provide full path to your physical device or logical volume.\n" ); exit; } + + push( @PARTITIONS, { 'name' => 'swap', 'size' => '', 'type' => 'swap', 'mountpoint' => '', 'options' => '', 'imagetype' => 'phy:', 'image' => $swap_img } ) + unless( $CONFIG{'noswap'} ); } - if (! -e $phys_img) + my $options = 'errors=remount-ro'; + if ( $CONFIG{'fs'} eq 'xfs' ) { - logprint( "The physical device or logical volume for image-dev $phys_img doesn't exist. Aborting.\n" ); - logprint( "NOTE: Please provide full path to your physical device or logical volume.\n" ); + $options = 'defaults'; + } + + if ( defined $CONFIG{'image-dev'} ) + { + $phys_img = $CONFIG{'image-dev'}; + + push( @PARTITIONS, { 'name' => 'disk', 'size' => '', 'type' => $CONFIG{'fs'}, 'mountpoint' => '/', 'options' => $options, 'imagetype' => 'phy:', 'image' => $phys_img } ); + } + else + { + logprint( "No image-dev parameter given. Aborting.\n" ); exit; } - createFilesystem( $phys_img ); + createFilesystem( $phys_img, $CONFIG{'fs'} ); createSwap( $swap_img ) unless ( $CONFIG{'noswap'} ); } @@ -2129,120 +2360,75 @@ sub usePhysicalDevice sub createLVMBits { - # The two volumes we will need to use.. - my $disk = $CONFIG{'hostname'} . "-disk" ; - my $swap = $CONFIG{'hostname'} . "-swap" ; - # # Check whether the disk volume exists already, and if so abort # unless '--force' is specified. # - my $lvm_disk = "/dev/$CONFIG{'lvm'}/$CONFIG{'hostname'}-disk"; - if ( -e $lvm_disk ) + foreach my $partition ( @PARTITIONS ) { - # Delete if forcing - if ( $CONFIG{'force'} ) + my $disk = $CONFIG{'hostname'} . '-' . $partition->{'name'}; + my $lvm_disk = "/dev/$CONFIG{'lvm'}/$disk"; + + if ( -e $lvm_disk ) { - logprint( "Removing $lvm_disk - since we're forcing the install\n" ); - runCommand( "lvremove --force $lvm_disk" ); - } - else - { - logprint( "The LVM disk image already exists. Aborting.\n" ); - logprint( "Specify '--force' to delete and recreate\n" ); - exit; - } - } - - - - # - # Check whether the swap volume exists already, and if so abort - # unless '--force' is specified. - # - my $lvm_swap = "/dev/$CONFIG{'lvm'}/$CONFIG{'hostname'}-swap"; - if ( -e $lvm_swap ) - { - # Delete if forcing - if ( $CONFIG{'force'} ) - { - logprint( "Removing $lvm_swap - since we're forcing the install\n" ); - runCommand( "lvremove --force $lvm_swap" ); - } - else - { - logprint( "The LVM swap image already exists. Aborting.\n" ); - logprint( "Specify '--force' to delete and recreate\n" ); - exit; - } - } - - - # - # Modify the sizes to something reasonable - # - my $disk_size = $CONFIG{'size'}; - my $swap_size = $CONFIG{'swap'}; - - # - # Convert Gb -> Mb for the disk image size, and swap size. - # - if ( $disk_size =~ /^(\d+)Gb*$/i ) - { - $disk_size = $1 * 1024 . "M"; - } - if ( $swap_size =~ /^(\d+)Gb*$/i ) - { - $swap_size = $1 * 1024 . "M"; - } - - # - # Final adjustments to sizing. - # - $disk_size =~ s/Mb*$/k/i; - if ( $swap_size =~ /^(\d+)Mb*$/i ) - { - $swap_size = $1; - } - - - # - # The commands to create the volumes. - # - my $disk_cmd = "lvcreate $CONFIG{'lvm'} -L $CONFIG{'size'}M -n $disk"; - my $swap_cmd = "lvcreate $CONFIG{'lvm'} -L $CONFIG{'swap'} -n $swap"; - - # - # Create the volumes - # - runCommand( $disk_cmd ); - runCommand( $swap_cmd ) unless( $CONFIG{'noswap'} ); - - # - # Make sure that worked. - # - if ( ! -e $lvm_disk ) - { - logprint( "The LVM disk image creation failed to create $lvm_disk.\n" ); - logprint( "aborting\n" ); - exit; - } - if ( ! -e $lvm_swap ) - { - unless( $CONFIG{'noswap'} ) - { - logprint( "The LVM disk image creation failed to create $swap.\n" ); - logprint( "aborting\n" ); + # Delete if forcing + if ( $CONFIG{'force'} ) + { + logprint( "Removing $lvm_disk - since we're forcing the install\n" ); + runCommand( "lvremove --force $lvm_disk" ); + } + else + { + logprint( "The LVM disk image already exists. Aborting.\n" ); + logprint( "Specify '--force' to delete and recreate\n" ); exit; + } } } + foreach my $partition ( @PARTITIONS ) + { + my $disk = $CONFIG{'hostname'} . '-' . $partition->{'name'}; + my $lvm_disk = "/dev/$CONFIG{'lvm'}/$disk"; - # - # Initialise the partitions with the relevant filesystem. - # - createFilesystem( "/dev/$CONFIG{'lvm'}/$CONFIG{'hostname'}-disk" ); - createSwap( "/dev/$CONFIG{'lvm'}/$CONFIG{'hostname'}-swap" ) unless ( $CONFIG{'noswap'} ); + # + # Save the image path to the partitions array + # + $partition->{'imagetype'} = 'phy:'; + $partition->{'image'} = $lvm_disk; + + # + # The commands to create the volume. + # + my $disk_cmd = "lvcreate $CONFIG{'lvm'} -L $partition->{'size'} -n $disk"; + + # + # Create the volume + # + runCommand( $disk_cmd ); + + # + # Make sure that worked. + # + if ( ! -e $lvm_disk ) + { + logprint( "The LVM partition image creation failed to create $lvm_disk.\n" ); + logprint( "aborting\n" ); + exit; + } + + # + # Finally create the filesystem / swap + # + if ( $partition->{'type'} eq 'swap' ) + { + createSwap( $lvm_disk ); + } + else + { + createFilesystem( $lvm_disk, $partition->{'type'} ); + } + } } @@ -2260,165 +2446,116 @@ sub createLVMBits sub createEVMSBits { - # The two volumes we will need to use.. - my $disk = $CONFIG{'hostname'} . "-disk" ; - my $swap = $CONFIG{'hostname'} . "-swap" ; - # # Check whether the disk volume exists already, and if so abort # unless '--force' is specified. This is two steps with evms, # because two things need to be checked, the volume and the object. # - # Check whether the EVMS volume already exists, abort unless '--force' is specified. - my $evms_volume_disk = "/dev/evms/$CONFIG{'hostname'}-disk"; - if ( -e $evms_volume_disk ) + foreach my $partition ( @PARTITIONS ) { - # Delete if forcing - if ( $CONFIG{'force'} ) + # Check whether the EVMS volume already exists, abort unless '--force' is specified. + my $evms_volume_disk = "/dev/evms/$CONFIG{'hostname'}-$partition->{'name'}"; + if ( -e $evms_volume_disk ) { - logprint( "Removing $evms_volume_disk - since we're forcing the install\n" ); - runCommand( "echo Delete : $evms_volume_disk | evms" ); + # Delete if forcing + if ( $CONFIG{'force'} ) + { + logprint( "Removing $evms_volume_disk - since we're forcing the install\n" ); + runCommand( "echo Delete : $evms_volume_disk | evms" ); + } + else + { + logprint( "The EVMS volume $evms_volume_disk already exists. Aborting.\n" ); + logprint( "Specify '--force' to delete and recreate\n" ); + exit; + } + } + + # + # Check whether the EVMS object exists, abort unless '--force' + # is specified. + # + # Note: $evms_object_disk is not specified directly as a device + # + my $evms_object_disk = "$CONFIG{'evms'}/$CONFIG{'hostname'}-$partition->{'name'}"; + if ( -e $evms_object_disk ) + { + # Delete if forcing + if ( $CONFIG{'force'} ) + { + logprint( "Removing $evms_object_disk - since we're forcing the install\n" ); + runCommand( "echo Delete : $evms_object_disk | evms" ); + } + else + { + logprint( "The EVMS object $evms_object_disk already exists. Aborting.\n" ); + logprint( "Specify '--force' to delete and recreate\n" ); + exit; + } + } + } + + foreach my $partition ( @PARTITIONS ) + { + my $disk = $CONFIG{'hostname'} . '-' . $partition->{'name'}; + my $evms_disk = "/dev/evms/$disk"; + + # + # Save the image path to the partitions array + # + $partition->{'imagetype'} = 'phy:'; + $partition->{'image'} = $evms_disk; + + # + # Modify the size to something reasonable + # + my $size = $partition->{'size'}; + + # + # Convert Gb -> Mb for the partition image size. + # + if ( $size =~ /^([0-9.]+)Gb*$/i ) + { + $size = $1 * 1024 . "M"; + } + + # + # Final adjustments to sizing. + # + $size =~ s/Mb*$/k/i; + + # + # The commands to create the objects and volumes. + # + # create the object + # + my $disk_cmd_object = "echo allocate : $CONFIG{'evms'}/Freespace, size=$CONFIG{'size'}, name=$disk | evms"; + + # + # these will be piped to evms, but gotta check it first + # + my $disk_cmd_volume = "echo create : Volume, $CONFIG{'evms'}/$disk, name=$disk | evms"; + + # + # Create the volumes + # + runCommand( $disk_cmd_object ); + runCommand( $disk_cmd_volume ); + + # + # Initialise the partition with the relevant filesystem. + # + if ( $partition->{'type'} eq 'swap' ) + { + createSwap( $disk_cmd_volume ); } else { - logprint( "The EVMS volume $evms_volume_disk already exists. Aborting.\n" ); - logprint( "Specify '--force' to delete and recreate\n" ); - exit; + createFilesystem( $disk_cmd_volume, $partition->{'type'} ); } } - # - # Check whether the EVMS object exists, abort unless '--force' - # is specified. - # - # Note: $evms_object_disk is not specified directly as a device - # - my $evms_object_disk = "$CONFIG{'evms'}/$CONFIG{'hostname'}-disk"; - if ( -e $evms_object_disk ) - { - # Delete if forcing - if ( $CONFIG{'force'} ) - { - logprint( "Removing $evms_object_disk - since we're forcing the install\n" ); - runCommand( "echo Delete : $evms_object_disk | evms" ); - } - else - { - logprint( "The EVMS object $evms_object_disk already exists. Aborting.\n" ); - logprint( "Specify '--force' to delete and recreate\n" ); - exit; - } - } - - - # - # Check whether the swap object and EVMS volume exists already, and - # if so abort unless '--force' is specified. - # - # - # Check whether the EVMS volume for swap already exists, abort - # unless '--force' is specified. - # - my $evms_volume_swap = "/dev/evms/$CONFIG{'hostname'}-swap"; - if ( -e $evms_volume_swap ) - { - # Delete if forcing - if ( $CONFIG{'force'} ) - { - logprint( "Removing $evms_volume_swap - since we're forcing the install\n" ); - runCommand( "echo Delete : $evms_volume_swap | evms" ); - } - else - { - logprint( "The EVMS volume $evms_volume_swap image already exists. Aborting.\n" ); - logprint( "Specify '--force' to delete and recreate\n" ); - exit; - } - } - # Check whether the evms object for swap exists, abort unless '--force' is specified. - # note that $evms_object_swap is not specified directly as a device - my $evms_object_swap = "$CONFIG{'evms'}/$CONFIG{'hostname'}-swap"; - if ( -e $evms_object_swap ) - { - # Delete if forcing - if ( $CONFIG{'force'} ) - { - logprint( "Removing $evms_object_swap - since we're forcing the install\n" ); - runCommand( "echo Delete : $evms_object_swap | evms" ); - } - else - { - logprint( "The EVMS object $evms_object_swap image already exists. Aborting.\n" ); - logprint( "Specify '--force' to delete and recreate\n" ); - exit; - } - } - - - # - # Modify the sizes to something reasonable - # - my $disk_size = $CONFIG{'size'}; - my $swap_size = $CONFIG{'swap'}; - - # - # Convert Gb -> Mb for the disk image size, and swap size. - # - if ( $disk_size =~ /^(\d+)Gb*$/i ) - { - $disk_size = $1 * 1024 . "M"; - } - if ( $swap_size =~ /^(\d+)Gb*$/i ) - { - $swap_size = $1 * 1024 . "M"; - } - - # - # Final adjustments to sizing. - # - $disk_size =~ s/Mb*$/k/i; - if ( $swap_size =~ /^(\d+)Mb*$/i ) - { - $swap_size = $1; - } - - - # - # The commands to create the objects and volumes. - # - # create the object - # - my $disk_cmd_object = "echo allocate : $CONFIG{'evms'}/Freespace, size=$CONFIG{'size'}, name=$disk | evms"; - - # - # these will be piped to evms, but gotta check it first - # - my $disk_cmd_volume = "echo create : Volume, $CONFIG{'evms'}/$disk, name=$disk | evms"; - - #repeat the same steps for the swap partition - my $swap_cmd_object = "echo allocate : $CONFIG{'evms'}/Freespace, size=$CONFIG{'swap'}, name=$swap | evms"; - - #create the EVMS volume - my $swap_cmd_volume = "echo create : Volume, $CONFIG{'evms'}/$swap, name=$swap | evms"; - ##/sbin/lvcreate $CONFIG{'evms'} -L $CONFIG{'swap'} -n $swap"; - - - # - # Create the volumes - # - runCommand( $disk_cmd_object ); - runCommand( $disk_cmd_volume ); - - runCommand( $swap_cmd_object ) unless( $CONFIG{'noswap'} ); - runCommand( $swap_cmd_volume ) unless( $CONFIG{'noswap'} ); - - # - # Initialise the partitions with the relevant filesystem. - # - createFilesystem( "/dev/evms/$CONFIG{'hostname'}-disk" ); - createSwap( "/dev/evms/$CONFIG{'hostname'}-swap" ) unless ( $CONFIG{'noswap'} ); - } @@ -2433,13 +2570,13 @@ sub createEVMSBits sub createFilesystem { - my( $image ) = ( @_ ); + my( $image, $fs ) = ( @_ ); # # We have the filesystem the user wanted, make sure that the # binary exists. # - my $command = $CONFIG{ "make_fs_" . $CONFIG{'fs'} }; + my $command = $CONFIG{ "make_fs_" . $fs }; # # Split the command into "binary" + "args". Make sure that @@ -2452,20 +2589,20 @@ sub createFilesystem if ( ! defined( findBinary( $binary ) ) ) { - logprint( "The binary '$binary' required to create the filesystem $CONFIG{'fs'} is missing\n" ); + logprint( "The binary '$binary' required to create the filesystem $fs is missing\n" ); exit; } } else { - logprint( "The filesystem creation hash is bogus for filesystem : $CONFIG{'fs'}\n" ); + logprint( "The filesystem creation hash is bogus for filesystem : $fs\n" ); exit; } # # OK we have the command and the filesystem. Create it. # - logprint( "\nCreating $CONFIG{'fs'} filesystem on $image\n" ); + logprint( "\nCreating $fs filesystem on $image\n" ); $command .= $image; @@ -2487,7 +2624,10 @@ sub createSwap { my ( $path ) = ( @_ ); + logprint( "\nCreating swap on $path\n" ); + runCommand( "mkswap $path" ); + logprint( "Done\n" ); } @@ -2503,68 +2643,48 @@ sub createSwap sub mountImage { - # - # Determine what we're to mount - # - my $image; - - if ( $CONFIG{'lvm'} ) - { - $image = "/dev/" . $CONFIG{'lvm'} . "/" . $CONFIG{'hostname'} . '-disk'; - } - elsif ( $CONFIG{'evms'} ) - { - $image = "/dev/evms/" . $CONFIG{'hostname'} . '-disk'; - } - elsif ( $CONFIG{'dir'} ) - { - $image = $CONFIG{'dir'} . '/domains/' . $CONFIG{'hostname'} . "/disk.img" ; - } - elsif ( $CONFIG{'image-dev'} ) - { - $image = $CONFIG{'image-dev'}; - } - else - { - logprint( "I don't know what to mount!\n" ); - logprint( "Please specify '--dir' or '--lvm' or '--evms' or '--image-dev'\n" ); - $FAIL = 1; - exit; - } - - # # Create a temporary mount-point to use for the image/volume. # $MOUNT_POINT = tempdir( CLEANUP => 1 ); - # - # Lookup the correct arguments to pass to mount. - # - my $mount_cmd; - my $mount_type = $CONFIG{'mount_fs_' . $CONFIG{'fs'} }; + foreach my $partition ( @PARTITIONS ) + { + if ( $partition->{'type'} ne 'swap' ) + { + my $image = $partition->{'image'}; + my $mountpoint = $MOUNT_POINT . $partition->{'mountpoint'}; - # - # LVM partition - # - if ( $CONFIG{'lvm'} ) - { - $mount_cmd = "mount $mount_type $image $MOUNT_POINT"; - } - elsif ( $CONFIG{'evms'} ) - { - $mount_cmd = "mount $mount_type $image $MOUNT_POINT"; - } - elsif ( $CONFIG{'image-dev'} ) - { - $mount_cmd = "mount $mount_type $image $MOUNT_POINT"; - } - else - { - $mount_cmd = "mount $mount_type -o loop $image $MOUNT_POINT"; - } - runCommand( $mount_cmd ); + mkpath( $mountpoint, 0, 0755 ); + # + # Lookup the correct arguments to pass to mount. + # + my $mount_cmd; + my $mount_type = $CONFIG{'mount_fs_' . $partition->{'type'} }; + + # + # LVM partition + # + if ( $CONFIG{'lvm'} ) + { + $mount_cmd = "mount $mount_type $image $mountpoint"; + } + elsif ( $CONFIG{'evms'} ) + { + $mount_cmd = "mount $mount_type $image $mountpoint"; + } + elsif ( $CONFIG{'image-dev'} ) + { + $mount_cmd = "mount $mount_type $image $mountpoint"; + } + else + { + $mount_cmd = "mount $mount_type -o loop $image $mountpoint"; + } + runCommand( $mount_cmd ); + } + } } @@ -2674,6 +2794,11 @@ sub exportEnvironment $CONFIG{'mirror'} = $CONFIG{$distMirror}; } + # + # Export partitions array to configuration + # + exportPartitionsToConfig(); + foreach my $key ( keys %CONFIG ) { if ( defined( $CONFIG{$key} ) ) diff --git a/bin/xt-create-xen-config b/bin/xt-create-xen-config index 58b72a6..2c5ad9f 100755 --- a/bin/xt-create-xen-config +++ b/bin/xt-create-xen-config @@ -103,7 +103,7 @@ xt-create-config - Create a Xen configuration file for a new guest -- http://www.steve.org.uk/ - $Id: xt-create-xen-config,v 1.40 2007-06-16 13:44:38 steve Exp $ + $Id: xt-create-xen-config,v 1.41 2007-07-07 23:48:09 steve Exp $ =cut @@ -136,6 +136,11 @@ use Text::Template; # my %CONFIG; +# +# Partition layout information values read from the partitions file. +# +my @PARTITIONS = undef; + # # Default options # @@ -225,7 +230,7 @@ sub parseCommandLineArguments if ( $VERSION ) { - my $REVISION = '$Revision: 1.40 $'; + my $REVISION = '$Revision: 1.41 $'; if ( $REVISION =~ /1.([0-9.]+) / ) { $REVISION = $1; @@ -287,6 +292,36 @@ sub checkArguments } +=begin doc + + Reconstructs the internal partitions array from the text representation exported by the xen-create-image script. + +=end doc + +=cut + +sub importPartitionsFromEnvironment +{ + @PARTITIONS = (); + + for (my $i=1; $i <= $ENV{'NUMPARTITIONS'}; $i++) + { + my @parts = split(/:/, $ENV{'PARTITION' . $i}, 7); + push( @PARTITIONS, + { + 'name' => $parts[0], + 'size' => $parts[1], + 'type' => $parts[2], + 'mountpoint' => $parts[3], + 'options' => $parts[4], + 'imagetype' => $parts[5], + 'image' => $parts[6] + } + ); + } +} + + =begin doc @@ -343,45 +378,38 @@ sub createXenConfig # # Images as presented to Xen - either loopback images, or LVM partitions. # - my $image_vbd; - my $swap_vbd; - if ( $ENV{'lvm'} ) { - $image_vbd = "phy:$ENV{'lvm'}/$ENV{'hostname'}-disk"; - $swap_vbd = "phy:$ENV{'lvm'}/$ENV{'hostname'}-swap"; + $ENV{'image_prefix'} = "phy:$ENV{'lvm'}/$ENV{'hostname'}-"; + $ENV{'image_suffix'} = ''; + importPartitionsFromEnvironment(); } elsif ( $ENV{'evms'} ) { - $image_vbd = "phy:/dev/evms/$ENV{'hostname'}-disk"; - $swap_vbd = "phy:/dev/evms/$ENV{'hostname'}-swap"; + $ENV{'image_prefix'} = "phy:/dev/evms/$ENV{'hostname'}-"; + $ENV{'image_suffix'} = ''; + importPartitionsFromEnvironment(); } elsif ( $ENV{'image-dev'} ) { - $image_vbd = "phy:$ENV{'image-dev'}"; + $ENV{'image_vbd'} = "phy:$ENV{'image-dev'}"; if ( $ENV{'swap-dev'} ) { - $swap_vbd = "phy:$ENV{'swap-dev'}"; + $ENV{'swap_vbd'} = "phy:$ENV{'swap-dev'}"; } else { - $swap_vbd = undef; + $ENV{'swap_vbd'} = undef; } } else { - $image_vbd = "file:$ENV{'dir'}/domains/$ENV{'hostname'}/disk.img"; - $swap_vbd = "file:$ENV{'dir'}/domains/$ENV{'hostname'}/swap.img"; + $ENV{'image_prefix'} = "file:$ENV{'dir'}/domains/$ENV{'hostname'}/"; + $ENV{'image_suffix'} = '.img'; + importPartitionsFromEnvironment(); } - # - # Setup the two devices in our environment. - # - $ENV{'image_vbd'} = $image_vbd; - $ENV{'swap_vbd'} = $swap_vbd; - - # # The xen-tools version. # @@ -398,6 +426,7 @@ sub createXenConfig { $vars{$key} = $ENV{$key}; } + $vars{'PARTITIONS'} = \@PARTITIONS; # # Now output the data. diff --git a/debian/changelog b/debian/changelog index 34932ea..d95d360 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +xen-tools (3.6-1) unstable; urgency=low + + * UNRELEASED. + - Partitioning support. + + -- Steve Kemp Sun, 16 Jun 2007 14:43:00 +0000 + xen-tools (3.5-1) unstable; urgency=low * Only add Debian sources for security.debian.org if enabled upon the host. diff --git a/debian/control b/debian/control index 2ec5e7b..a771910 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Standards-Version: 3.7.2 Package: xen-tools Architecture: all -Depends: debootstrap, perl-modules, libtext-template-perl +Depends: debootstrap, perl-modules, libtext-template-perl, libconfig-inifiles-perl Recommends: xen-hypervisor-amd64 | xen-hypervisor-i386 | xen-hypervisor-i386-pae, reiserfsprogs, xfsprogs, rpmstrap, perl-doc, xen-shell, libexpect-perl Description: Tools to manage debian XEN virtual servers This package contains tools to manage Debian based XEN virtual servers. diff --git a/etc/xm.tmpl b/etc/xm.tmpl index d7ebdb7..b7d4554 100644 --- a/etc/xm.tmpl +++ b/etc/xm.tmpl @@ -21,15 +21,20 @@ memory = '{$memory}' # # Disk device(s). # -root = '/dev/{$device}1 ro' -{ if ( $noswap ) +{ + for ( my $i = 0; $i <= $#PARTITIONS; $i++ ) { - $OUT .= "disk = [ '$image_vbd,$device" . "1,w' ]"; + if ( $PARTITIONS[$i]{'mountpoint'} eq '/' ) + { + $OUT .= "root = '/dev/$device" . ($i + 1) . " ro'\n"; + } } - else + $OUT .= "disk = [\n"; + for ( my $i = 0; $i <= $#PARTITIONS; $i++ ) { - $OUT .= "disk = [ '$image_vbd,$device" . "1,w', '$swap_vbd,$device" . "2,w' ]"; + $OUT .= " '$PARTITIONS[$i]{'imagetype'}$PARTITIONS[$i]{'image'},$device" . ( $i + 1 ) .",w',\n"; } + $OUT .= " ]\n"; } # @@ -81,4 +86,4 @@ on_crash = 'restart' { $OUT .= "xen_shell = '$admins'\n"; } -} \ No newline at end of file +} diff --git a/hooks/centos4/90-make-fstab b/hooks/centos4/90-make-fstab index 94edb53..841fd33 100755 --- a/hooks/centos4/90-make-fstab +++ b/hooks/centos4/90-make-fstab @@ -30,20 +30,6 @@ fi logMessage Script $0 starting -# -# Options to mount the root filesystem with, we need to have -# different options for xfs. -# -# The default option works for ext2, ext3, and reiserfs. -# -options="errors=remount-ro" - -case "${fs}" in - xfs) - options="defaults" - ;; -esac - logMessage Filesystem options are ${options} @@ -58,36 +44,52 @@ fi # # Now we have the options we can create the fstab. # +has_xfs=0 +has_reiserfs=0 cat < ${prefix}/etc/fstab -/dev/${device}1 / ${fs} ${options} 0 1 -proc /proc proc rw,nodev,nosuid,noexec 0 0 -E_O_FSTAB - - +# /etc/fstab: static file system information. # -# Add in the swap unless it is disabled -# -if [ "${noswap}" ]; then - : -else -cat <> ${prefix}/etc/fstab -/dev/${device}2 none swap sw 0 0 +# +proc /proc proc defaults 0 0 E_O_FSTAB -fi +for part in `seq 1 ${NUMPARTITIONS}`; do + eval "PARTITION=\"\${PARTITION${part}}\"" + OLDIFS="${IFS}" + IFS=: + x=0 + for partdata in ${PARTITION}; do + eval "partdata${x}=\"${partdata}\"" + x=$(( x+1 )) + done + IFS="${OLDIFS}" + + case "${partdata2}" in + xfs) + has_xfs=1 + ;; + reiserfs) + has_reiserfs=1 + ;; + esac + + if [ "${partdata2}" = "swap" ]; then + echo "/dev/${device}${part} none swap sw 0 0" >> ${prefix}/etc/fstab + else + echo "/dev/${device}${part} ${partdata3} ${partdata2} ${partdata4} 0 1" >> ${prefix}/etc/fstab + fi +done # # Finally we can install any required packages for the given root # filesystem # -#case "${fs}" in -# xfs) -# install_package xfsprogs -# ;; -# reiserfs) -# install_package reiserfsprogs -# ;; -#esac +#if [ $has_xfs -eq 1 ]; then +# installDebianPackage ${prefix} xfsprogs +#fi +#if [ $has_reiserfs -eq 1 ]; then +# installDebianPackage ${prefix} reiserfsprogs +#fi # diff --git a/hooks/dapper/80-install-modules b/hooks/dapper/80-install-modules index 1ea6379..f2be87d 100755 --- a/hooks/dapper/80-install-modules +++ b/hooks/dapper/80-install-modules @@ -41,7 +41,16 @@ linux_modules_package="linux-modules-$(uname -r)" # Attempt to install that package. This will either work on an Etch # system, or fail on a Sarge/custom kernel. # -if chroot ${prefix} /usr/bin/apt-cache show ${linux_modules_package} >/dev/null 2>/dev/null; then +if [ -n "${modules}" -a -d "${modules}" ]; then + + # + # Modules path was specified during install + # + logMessage "Copying modules from ${modules}" + + mkdir -p ${prefix}/lib/modules + cp -au ${modules} ${prefix}/lib/modules +elif chroot ${prefix} /usr/bin/apt-cache show ${linux_modules_package} >/dev/null 2>/dev/null; then logMessage "Package '${linux_modules_package}' is available - installing" diff --git a/hooks/dapper/90-make-fstab b/hooks/dapper/90-make-fstab index 5ee3b75..9efa5fd 100755 --- a/hooks/dapper/90-make-fstab +++ b/hooks/dapper/90-make-fstab @@ -30,24 +30,6 @@ fi logMessage Script $0 starting -# -# Options to mount the root filesystem with, we need to have -# different options for xfs. -# -# The default option works for ext2 & ext3. -# -options="errors=remount-ro" - -case "${fs}" in - xfs) - options="defaults" - ;; - reiserfs) - options="defaults" - ;; -esac - - # # Make sure we use ide style device names if required # @@ -59,35 +41,52 @@ fi # # Now we have the options we can create the fstab. # +has_xfs=0 +has_reiserfs=0 cat < ${prefix}/etc/fstab -/dev/${device}1 / ${fs} ${options} 0 1 -proc /proc proc rw,nodev,nosuid,noexec 0 0 -E_O_FSTAB - +# /etc/fstab: static file system information. # -# Add in the swap unless it is disabled -# -if [ "${noswap}" ]; then - : -else -cat <> ${prefix}/etc/fstab -/dev/${device}2 none swap sw 0 0 +# +proc /proc proc defaults 0 0 E_O_FSTAB -fi +for part in `seq 1 ${NUMPARTITIONS}`; do + eval "PARTITION=\"\${PARTITION${part}}\"" + OLDIFS="${IFS}" + IFS=: + x=0 + for partdata in ${PARTITION}; do + eval "partdata${x}=\"${partdata}\"" + x=$(( x+1 )) + done + IFS="${OLDIFS}" + + case "${partdata2}" in + xfs) + has_xfs=1 + ;; + reiserfs) + has_reiserfs=1 + ;; + esac + + if [ "${partdata2}" = "swap" ]; then + echo "/dev/${device}${part} none swap sw 0 0" >> ${prefix}/etc/fstab + else + echo "/dev/${device}${part} ${partdata3} ${partdata2} ${partdata4} 0 1" >> ${prefix}/etc/fstab + fi +done # # Finally we can install any required packages for the given root # filesystem # -case "${fs}" in - xfs) - installDebianPackage ${prefix} xfsprogs - ;; - reiserfs) - installDebianPackage ${prefix} reiserfsprogs - ;; -esac +if [ $has_xfs -eq 1 ]; then + installDebianPackage ${prefix} xfsprogs +fi +if [ $has_reiserfs -eq 1 ]; then + installDebianPackage ${prefix} reiserfsprogs +fi # diff --git a/hooks/debian/15-disable-hwclock b/hooks/debian/15-disable-hwclock index 132f4da..64fa4af 100755 --- a/hooks/debian/15-disable-hwclock +++ b/hooks/debian/15-disable-hwclock @@ -29,9 +29,20 @@ logMessage Script $0 starting # # Disable the startup scripts from all runlevels. # -chmod -x ${prefix}/etc/init.d/hwclock.sh -chmod -x ${prefix}/etc/init.d/hwclockfirst.sh +if [ -x ${prefix}/etc/init.d/hwclock.sh ]; then + chmod -x ${prefix}/etc/init.d/hwclock.sh +else + + logMessage "/etc/init.d/hwclock.sh not found. skipping." +fi +if [ -x ${prefix}/etc/init.d/hwclockfirst.sh ]; then + + chmod -x ${prefix}/etc/init.d/hwclockfirst.sh +else + + logMessage "/etc/init.d/hwclockfirst.sh not found. skipping." +fi # diff --git a/hooks/debian/55-create-dev b/hooks/debian/55-create-dev index b692512..5b49526 100755 --- a/hooks/debian/55-create-dev +++ b/hooks/debian/55-create-dev @@ -32,6 +32,14 @@ logMessage Script $0 starting # should speed up installs which use --copy/--tar # if ( test `ls -1 ${prefix}/dev | wc -l` -gt 10 ); then + # + # We still need to make sure the basic devices are present + # + cd ${prefix}/dev + ./MAKEDEV std + ./MAKEDEV hda + ./MAKEDEV sda + logMessage "Terminating because there appear to be files in /dev already" exit fi diff --git a/hooks/debian/80-install-modules b/hooks/debian/80-install-modules index 684ca65..438ea73 100755 --- a/hooks/debian/80-install-modules +++ b/hooks/debian/80-install-modules @@ -41,7 +41,16 @@ linux_modules_package="linux-modules-$(uname -r)" # Attempt to install that package. This will either work on an Etch # system, or fail on a Sarge/custom kernel. # -if chroot ${prefix} /usr/bin/apt-cache show ${linux_modules_package} >/dev/null 2>/dev/null; then +if [ -n "${modules}" -a -d "${modules}" ]; then + + # + # Modules path was specified during install + # + logMessage "Copying modules from ${modules}" + + mkdir -p ${prefix}/lib/modules + cp -au ${modules} ${prefix}/lib/modules +elif chroot ${prefix} /usr/bin/apt-cache show ${linux_modules_package} >/dev/null 2>/dev/null; then logMessage "Package '${linux_modules_package}' is available - installing" diff --git a/hooks/debian/90-make-fstab b/hooks/debian/90-make-fstab index 5ee3b75..c8c71b6 100755 --- a/hooks/debian/90-make-fstab +++ b/hooks/debian/90-make-fstab @@ -11,7 +11,6 @@ # -- # http://www.steve.org.uk/ - prefix=$1 # @@ -30,24 +29,6 @@ fi logMessage Script $0 starting -# -# Options to mount the root filesystem with, we need to have -# different options for xfs. -# -# The default option works for ext2 & ext3. -# -options="errors=remount-ro" - -case "${fs}" in - xfs) - options="defaults" - ;; - reiserfs) - options="defaults" - ;; -esac - - # # Make sure we use ide style device names if required # @@ -59,35 +40,52 @@ fi # # Now we have the options we can create the fstab. # +has_xfs=0 +has_reiserfs=0 cat < ${prefix}/etc/fstab -/dev/${device}1 / ${fs} ${options} 0 1 -proc /proc proc rw,nodev,nosuid,noexec 0 0 -E_O_FSTAB - +# /etc/fstab: static file system information. # -# Add in the swap unless it is disabled -# -if [ "${noswap}" ]; then - : -else -cat <> ${prefix}/etc/fstab -/dev/${device}2 none swap sw 0 0 +# +proc /proc proc defaults 0 0 E_O_FSTAB -fi +for part in `seq 1 ${NUMPARTITIONS}`; do + eval "PARTITION=\"\${PARTITION${part}}\"" + OLDIFS="${IFS}" + IFS=: + x=0 + for partdata in ${PARTITION}; do + eval "partdata${x}=\"${partdata}\"" + x=$(( x+1 )) + done + IFS="${OLDIFS}" + + case "${partdata2}" in + xfs) + has_xfs=1 + ;; + reiserfs) + has_reiserfs=1 + ;; + esac + + if [ "${partdata2}" = "swap" ]; then + echo "/dev/${device}${part} none swap sw 0 0" >> ${prefix}/etc/fstab + else + echo "/dev/${device}${part} ${partdata3} ${partdata2} ${partdata4} 0 1" >> ${prefix}/etc/fstab + fi +done # # Finally we can install any required packages for the given root # filesystem # -case "${fs}" in - xfs) - installDebianPackage ${prefix} xfsprogs - ;; - reiserfs) - installDebianPackage ${prefix} reiserfsprogs - ;; -esac +if [ $has_xfs -eq 1 ]; then + installDebianPackage ${prefix} xfsprogs +fi +if [ $has_reiserfs -eq 1 ]; then + installDebianPackage ${prefix} reiserfsprogs +fi # diff --git a/hooks/debian/95-configure-locales b/hooks/debian/95-configure-locales index b45553c..7d1713f 100755 --- a/hooks/debian/95-configure-locales +++ b/hooks/debian/95-configure-locales @@ -38,11 +38,6 @@ fi installDebianPackage ${prefix} locales installDebianPackage ${prefix} util-linux-locales -# -# Now generate the actual locale files. -# -chroot ${prefix} /usr/sbin/locale-gen - # diff --git a/hooks/edgy/80-install-modules b/hooks/edgy/80-install-modules index 1ea6379..f2be87d 100755 --- a/hooks/edgy/80-install-modules +++ b/hooks/edgy/80-install-modules @@ -41,7 +41,16 @@ linux_modules_package="linux-modules-$(uname -r)" # Attempt to install that package. This will either work on an Etch # system, or fail on a Sarge/custom kernel. # -if chroot ${prefix} /usr/bin/apt-cache show ${linux_modules_package} >/dev/null 2>/dev/null; then +if [ -n "${modules}" -a -d "${modules}" ]; then + + # + # Modules path was specified during install + # + logMessage "Copying modules from ${modules}" + + mkdir -p ${prefix}/lib/modules + cp -au ${modules} ${prefix}/lib/modules +elif chroot ${prefix} /usr/bin/apt-cache show ${linux_modules_package} >/dev/null 2>/dev/null; then logMessage "Package '${linux_modules_package}' is available - installing" diff --git a/hooks/edgy/90-make-fstab b/hooks/edgy/90-make-fstab index 5ee3b75..9efa5fd 100755 --- a/hooks/edgy/90-make-fstab +++ b/hooks/edgy/90-make-fstab @@ -30,24 +30,6 @@ fi logMessage Script $0 starting -# -# Options to mount the root filesystem with, we need to have -# different options for xfs. -# -# The default option works for ext2 & ext3. -# -options="errors=remount-ro" - -case "${fs}" in - xfs) - options="defaults" - ;; - reiserfs) - options="defaults" - ;; -esac - - # # Make sure we use ide style device names if required # @@ -59,35 +41,52 @@ fi # # Now we have the options we can create the fstab. # +has_xfs=0 +has_reiserfs=0 cat < ${prefix}/etc/fstab -/dev/${device}1 / ${fs} ${options} 0 1 -proc /proc proc rw,nodev,nosuid,noexec 0 0 -E_O_FSTAB - +# /etc/fstab: static file system information. # -# Add in the swap unless it is disabled -# -if [ "${noswap}" ]; then - : -else -cat <> ${prefix}/etc/fstab -/dev/${device}2 none swap sw 0 0 +# +proc /proc proc defaults 0 0 E_O_FSTAB -fi +for part in `seq 1 ${NUMPARTITIONS}`; do + eval "PARTITION=\"\${PARTITION${part}}\"" + OLDIFS="${IFS}" + IFS=: + x=0 + for partdata in ${PARTITION}; do + eval "partdata${x}=\"${partdata}\"" + x=$(( x+1 )) + done + IFS="${OLDIFS}" + + case "${partdata2}" in + xfs) + has_xfs=1 + ;; + reiserfs) + has_reiserfs=1 + ;; + esac + + if [ "${partdata2}" = "swap" ]; then + echo "/dev/${device}${part} none swap sw 0 0" >> ${prefix}/etc/fstab + else + echo "/dev/${device}${part} ${partdata3} ${partdata2} ${partdata4} 0 1" >> ${prefix}/etc/fstab + fi +done # # Finally we can install any required packages for the given root # filesystem # -case "${fs}" in - xfs) - installDebianPackage ${prefix} xfsprogs - ;; - reiserfs) - installDebianPackage ${prefix} reiserfsprogs - ;; -esac +if [ $has_xfs -eq 1 ]; then + installDebianPackage ${prefix} xfsprogs +fi +if [ $has_reiserfs -eq 1 ]; then + installDebianPackage ${prefix} reiserfsprogs +fi # diff --git a/hooks/fedora/90-make-fstab b/hooks/fedora/90-make-fstab index 06f569b..77bbe47 100755 --- a/hooks/fedora/90-make-fstab +++ b/hooks/fedora/90-make-fstab @@ -30,23 +30,6 @@ fi logMessage Script $0 starting -# -# Options to mount the root filesystem with, we need to have -# different options for xfs. -# -# The default option works for ext2, ext3, and reiserfs. -# -options="errors=remount-ro" - -case "${fs}" in - xfs) - options="defaults" - ;; -esac - -logMessage Filesystem options are ${options} - - # # Make sure we use ide style device names if required # @@ -58,37 +41,52 @@ fi # # Now we have the options we can create the fstab. # +has_xfs=0 +has_reiserfs=0 cat < ${prefix}/etc/fstab -/dev/${device}1 / ${fs} ${options} 0 1 -proc /proc proc rw,nodev,nosuid,noexec 0 0 -E_O_FSTAB - - +# /etc/fstab: static file system information. # -# Add in the swap unless it is disabled -# -if [ "${noswap}" ]; then - : -else -cat <> ${prefix}/etc/fstab -/dev/${device}2 none swap sw 0 0 +# +proc /proc proc defaults 0 0 E_O_FSTAB -fi - +for part in `seq 1 ${NUMPARTITIONS}`; do + eval "PARTITION=\"\${PARTITION${part}}\"" + OLDIFS="${IFS}" + IFS=: + x=0 + for partdata in ${PARTITION}; do + eval "partdata${x}=\"${partdata}\"" + x=$(( x+1 )) + done + IFS="${OLDIFS}" + + case "${partdata2}" in + xfs) + has_xfs=1 + ;; + reiserfs) + has_reiserfs=1 + ;; + esac + + if [ "${partdata2}" = "swap" ]; then + echo "/dev/${device}${part} none swap sw 0 0" >> ${prefix}/etc/fstab + else + echo "/dev/${device}${part} ${partdata3} ${partdata2} ${partdata4} 0 1" >> ${prefix}/etc/fstab + fi +done # # Finally we can install any required packages for the given root # filesystem # -#case "${fs}" in -# xfs) -# install_package xfsprogs -# ;; -# reiserfs) -# install_package reiserfsprogs -# ;; -#esac +#if [ $has_xfs -eq 1 ]; then +# installDebianPackage ${prefix} xfsprogs +#fi +#if [ $has_reiserfs -eq 1 ]; then +# installDebianPackage ${prefix} reiserfsprogs +#fi # diff --git a/hooks/gentoo/90-make-fstab b/hooks/gentoo/90-make-fstab index 36b4846..77bbe47 100755 --- a/hooks/gentoo/90-make-fstab +++ b/hooks/gentoo/90-make-fstab @@ -30,21 +30,6 @@ fi logMessage Script $0 starting -# -# Options to mount the root filesystem with, we need to have -# different options for xfs. -# -# The default option works for ext2, ext3, and reiserfs. -# -options="errors=remount-ro" - -case "${fs}" in - xfs) - options="defaults" - ;; -esac - - # # Make sure we use ide style device names if required # @@ -56,22 +41,52 @@ fi # # Now we have the options we can create the fstab. # +has_xfs=0 +has_reiserfs=0 cat < ${prefix}/etc/fstab -/dev/${device}1 / ${fs} ${options} 0 1 -proc /proc proc rw,nodev,nosuid,noexec 0 0 +# /etc/fstab: static file system information. +# +# +proc /proc proc defaults 0 0 E_O_FSTAB +for part in `seq 1 ${NUMPARTITIONS}`; do + eval "PARTITION=\"\${PARTITION${part}}\"" + OLDIFS="${IFS}" + IFS=: + x=0 + for partdata in ${PARTITION}; do + eval "partdata${x}=\"${partdata}\"" + x=$(( x+1 )) + done + IFS="${OLDIFS}" + + case "${partdata2}" in + xfs) + has_xfs=1 + ;; + reiserfs) + has_reiserfs=1 + ;; + esac + + if [ "${partdata2}" = "swap" ]; then + echo "/dev/${device}${part} none swap sw 0 0" >> ${prefix}/etc/fstab + else + echo "/dev/${device}${part} ${partdata3} ${partdata2} ${partdata4} 0 1" >> ${prefix}/etc/fstab + fi +done # -# Add in the swap unless it is disabled +# Finally we can install any required packages for the given root +# filesystem # -if [ "${noswap}" ]; then - : -else -cat <> ${prefix}/etc/fstab -/dev/${device}2 none swap sw 0 0 -E_O_FSTAB -fi +#if [ $has_xfs -eq 1 ]; then +# installDebianPackage ${prefix} xfsprogs +#fi +#if [ $has_reiserfs -eq 1 ]; then +# installDebianPackage ${prefix} reiserfsprogs +#fi # diff --git a/misc/xen-tools b/misc/xen-tools index df34d56..31f737d 100644 --- a/misc/xen-tools +++ b/misc/xen-tools @@ -18,7 +18,7 @@ # -- # http://www.steve.org.uk # -# $Id: xen-tools,v 1.49 2007-06-19 10:47:56 steve Exp $ +# $Id: xen-tools,v 1.50 2007-07-07 23:48:44 steve Exp $ # @@ -48,7 +48,7 @@ function _find_xen_images # _xen_create_image() { - local cur prev ip roles dists vgs + local cur prev ip roles partitions dists vgs COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} @@ -137,6 +137,11 @@ _xen_create_image() COMPREPLY=( $( compgen -W '${roles}' -- "${COMP_WORDS[COMP_CWORD]}" ) ) return 0 ;; + --partitions) + partitions=$(for x in `ls -1 /etc/xen-tools/partitions.d/ 2>/dev/null | grep -v \/ 2>/dev/null`; do echo ${x} ; done ) + COMPREPLY=( $( compgen -W '${partitions}' -- "${COMP_WORDS[COMP_CWORD]}" ) ) + return 0 + ;; esac if [[ ${cur} == -* ]]; then diff --git a/partitions/sample-server b/partitions/sample-server new file mode 100644 index 0000000..ef15c41 --- /dev/null +++ b/partitions/sample-server @@ -0,0 +1,45 @@ +[root] +size=1G +type=ext3 +mountpoint=/ +options=sync,errors=remount-ro + +[swap] +size=2G +type=swap + +[home] +size=1G +type=xfs +mountpoint=/home +options=nodev,nosuid + +[opt] +size=1.5G +type=xfs +mountpoint=/opt +options=nodev + +[tmp] +size=0.5G +type=xfs +mountpoint=/tmp +options=nodev,nosuid + +[usr] +size=4G +type=xfs +mountpoint=/usr +options=nodev + +[var] +size=4G +type=xfs +mountpoint=/var +options=nodev,nosuid + +[var-tmp] +size=1.5G +type=xfs +mountpoint=/var/tmp +options=nodev,nosuid diff --git a/tests/modules.t b/tests/modules.t index 86923f5..4206b3a 100644 --- a/tests/modules.t +++ b/tests/modules.t @@ -14,6 +14,10 @@ BEGIN{ use_ok( 'Config' ); } require_ok( 'Config' ); +BEGIN{ use_ok( 'Config::IniFiles' ); } +require_ok( 'Config::IniFiles' ); + + BEGIN{ use_ok( 'Digest::MD5' ); } require_ok( 'Digest::MD5' ); diff --git a/tests/xt-create-xen-config.t b/tests/xt-create-xen-config.t index 886998e..2746a94 100644 --- a/tests/xt-create-xen-config.t +++ b/tests/xt-create-xen-config.t @@ -5,7 +5,7 @@ # # Steve # -- -# $Id: xt-create-xen-config.t,v 1.4 2006-08-17 21:01:46 steve Exp $ +# $Id: xt-create-xen-config.t,v 1.5 2007-07-07 23:49:02 steve Exp $ # @@ -128,8 +128,8 @@ sub runCreateCommand # # Create a temporary directory, and make sure it is present. # - my $dir = File::Temp::tempdir( CLEANUP => 1 ); - ok ( -d $dir, "The temporary directory was created." ); + my $dir = File::Temp::tempdir( CLEANUP => 0 ); + ok ( -d $dir, "The temporary directory was created: $dir" ); # # Save the environment.