3
# Ubuntu Jeos image builder
4
# Copyright (C) 2007-2008 Canonical Ltd.
6
# Authors: Soren Hansen <soren@canonical.com>
7
# Neal McBurnett <neal@mcburnett.org>
8
# Michael Vogt <michael.vogt@ubuntu.com>
10
# Nick Barcet <nick.barcet@ubuntu.com>
11
# Onno Benschop <onno@itmaze.com.au>
13
# This program is free software; you can redistribute it and/or modify
14
# it under the terms of the GNU General Public License as published by
15
# the Free Software Foundation; either version 2 of the License, or
16
# (at your option) any later version.
18
# This program is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
# GNU General Public License for more details.
23
# You should have received a copy of the GNU General Public License along
24
# with this program; if not, write to the Free Software Foundation, Inc.,
25
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28
# create launchjeos command for vmware vm's
29
# review security of running as root, messing with $DESTINATION
31
test -n "$TMPDIR" || TMPDIR=""
32
# make sure variables are initialized and script quits when error are encountered
39
if [ -n "$VERBOSE" ]; then
44
# Keep perl inside the chroot quiet
48
# array to hold list of raw "files" to use
55
usage: ubuntu-vm-builder <vm> <suite>
57
[(-a|--arch) [(amd64|i386|lpia]]
58
[(-d|--dest) <destination (directory)>]
66
[--security-mirror URL]
74
[--part partitionfile]
78
[--kernel-flavour <flavour>]
79
[--components <comma separated list of components>]
80
[--ssh-key <public key file>]
81
[--ssh-user-key <public key file>]
82
[--exec <script to execute>]
83
[--firstboot <script to execute>]
84
[--firstlogin <script to execute>]
92
vm Generate image for the specified virtualisation software.
93
Valid choices are: vmw6 vmserver vbox qemu kvm
94
suite Use the specified Ubuntu suite.
95
Valid options: intrepid, intrepid, hardy, gutsy, feisty, edgy, dapper
96
--addpkg PKG Install PKG into the guest (can be specfied multiple times)
97
-a, --arch ARCH Specify the target architecture.
98
Valid options: amd64 i386 lpia (defaults to host arch)
99
-d, --dest Specify the destination directory.
100
Default: ubuntu-vm-<SUITE>-<ARCH>-<HOSTNAME>
101
-o, --overwrite Force overwrite of destination directory if it already exist
102
-c PATH Specify a optional configuration file (default: ~/.ubuntu-vm-builder)
103
--domain DOMAIN Set DOMAIN as the domain name of the guest. Default:
104
The domain of the machine running this script.
105
-h, --help This help text.
106
-v, --verbose Show a lot of information as the vm is generated.
107
--hostname NAME Set NAME as the hostname of the guest. Default: ubuntu
108
Also uses this name as the VM name
109
--mem NN Assign NN megabytes of memory to the guest vm.
111
--mirror URL Use Ubuntu mirror at URL instead of the default, which
112
is http://archive.ubuntu.com/ubuntu for official arches
113
and http://ports.ubuntu.com/ubuntu-ports otherwise
114
--security-mirror URL
115
Use Ubuntu security mirror at URL instead of the default,
116
which is http://security.ubuntu.com/ubuntu for official
117
arches and http://ports.ubuntu.com/ubuntu-ports otherwise
118
--iso PATH Use an iso image as the source for installation of file.
119
Full path to the iso must be provided. If --mirror is also
120
provided, it will be used in the final sources.list of the vm.
121
This requires suite and kernel parameter to match what is
122
available on the iso, obviously.
123
--removepkg PKG Remove PKG from the guest (can be specfied multiple times)
124
-t, --tmp TMPDIR Use TMPDIR as temporary working area for the image
125
generation. Defaults \$TMPDIR if it is defined, or /tmp otherwise.
126
If it is set to "-", working data will go in same directory as -d
127
if specified with a full path or the current directory if not.
128
--tmpfs OPTIONS Use a tmpfs as the working directory, specifying its size or
129
"-" to use tmpfs default (suid,dev,size=1G).
130
--user USERNAME Set the name of the user to be added. Default: ubuntu.
131
--name FULLNAME Set the full name of the user to be added. Default: Ubuntu.
132
--pass PASSWORD Set the password for the user. Default: ubuntu.
133
--raw PATH Specify a raw file or device to install in. Can be specified
134
multiple time in conjunction with --part, paths will be used in
135
the order presented. In any case you are to insure that the raw
136
element(s) specified have enough free space.
137
--part PATH Allows to specify a partition table in partfile pointed by PATH
138
each line of partfile should specify (root first):
140
where size is in megabytes. You can have up to 4 virtual
141
disks, a new disk starts on a line with ---
149
The following three options are not used if --part is specified:
150
--rootsize SIZE The size in MB of the root filesystem (default 4096)
151
--optsize SIZE The size in MB of the /opt filesystem. If not set, no /opt
152
filesystem will be added.
153
--swapsize SIZE The size in MB of the swap partition (default 1024)
154
--kernel-flavour FLAVOUR
155
The kernel image flavour to install (default: virtual for
156
>= gutsy on i386, lpia on lpia, server otherwise)
157
--components COMP A comma seperated list of distro components to include
158
(e.g. main,universe). This defaults to "main"
159
--ssh-key PATH Add the given ssh public key file (absolute path)
160
to root's authorized keys and install openssh-server
161
--in-place Install directly into the filesystem images. This is needed
162
if your \$TMPDIR is nodev and/or nosuid, but will result in
163
slightly larger file system images.
164
(WARNING: this has strong security implications)
166
Add the given ssh key file (absolute path)
167
to the user's authorized key and install openssh-server.
168
--exec PATH Run the given script file. You can use
169
'chroot root <cmd>' to execute code in the guest.
170
See 'man ubuntu-vm-builder' for more explanations
171
--firstboot PATH Specify a script that will be copied into the guest and
172
executed the first time the machine boots. This script
173
must not be interactive.
174
--firstlogin PATH Specify a script that will be copied into the guest and
175
will be executed the first time the user logs in. This
176
script can be interactive.
177
--ip ADDRESS Ip address in dotted form
178
(defaults to dhcp if not specified)
180
Options below are discarded if --ip is not specified
181
--mask VALUE IP mask in dotted form (default: 255.255.255.0)
182
--net VALUE IP net address (default: X.X.X.0)
183
--bcast VALUE IP broadcast (default: X.X.X.255)
184
--gw ADDRESS Gateway address (default: X.X.X.1)
185
--dns ADDRESS Name server address (default: X.X.X.1)
187
('*' denotes default option)
192
# Emit usage info specific to each vm type
194
for vm in /usr/share/ubuntu-vm-builder/vms/*
196
vm="`basename "$vm"`"
197
echo "Options specific for vm type $vm:"
198
/usr/share/ubuntu-vm-builder/vms/$vm usage
203
ubuntu-vm-builder is Copyright (C) 2007-2008 Canonical Ltd. and
204
written by Soren Hansen <soren@canonical.com>.
208
if [ ! "`id -u`" = 0 ]
210
echo "$0 must be run as root (e.g. by means of sudo)"
216
echo "Please specify vm and suite"
222
# Import a stack of sanity checks
224
. /usr/share/ubuntu-vm-builder/sanity-checks
227
# First arg is the vm tech to use
231
. /usr/share/ubuntu-vm-builder/vms/$VM
235
# Second arg is the Ubuntu suite to install
239
. /usr/share/ubuntu-vm-builder/suites/$SUITE
242
# read default config from ~/.ubuntu-vm-builder and initialize variables
243
. /usr/share/ubuntu-vm-builder/config-handler
245
set +e; trap "usage;exit 1" ERR
246
TEMP=`getopt -o a:d:ohs:t:vc: --long addpkg:,arch:,dest:,overwrite,domain:,help,hostname:,mem:,mirror:,security-mirror:,iso:,removepkg:,suite:,tmp:,tmpfs:,vm:,user:,name:,pass:,part:,rootsize:,swapsize:,optsize:,raw:,ip:,mask:,net:,bcast:,gw:,dns:,kernel-flavour:,components:,ssh-key:,ssh-user-key:,no-opt,exec:,firstboot:,firstlogin:,verbose,in-place,$vm_getopt_args -- "$@"`
264
if [ ! "${2#/}" = "${2}" ]
266
# Absolute path given
269
# Relative path given
270
DESTINATION="${PWD}/$2"
303
PKGCMD="$PKGCMD ${2}-"
404
echo "Ignored obsolete --no-opt option"
412
# already handled in config-handler
416
INSTALL_IN_PLACE="YEAH"
425
vm_getopt "$@" || true
426
if [ $argsused -gt 0 ]
430
# This code will never be used as getopt will have caught it
431
# The vm had no clue what this was either
432
echo "Unknown option: $1"
445
ARCH=`dpkg --print-architecture`
448
if [ -z "$KERNEL_FLAVOUR" ]
452
check_kernel_flavour "$KERNEL_FLAVOUR"
454
info "kernel: $KERNEL_FLAVOUR"
456
if [ -n "$VMTMPDIR" ]
458
if [ "$VMTMPDIR" = "-" ]; then
459
if [ ! "${DESTINATION#/}" = "${DESTINATION}" ]; then
460
VMTMPDIR=$(dirname $DESTINATION)
466
if [ -n "$TMPDIR" ]; then
473
TEMPLATEDIR=${TEMPLATEDIR:-/usr/share/ubuntu-vm-builder/templates}
475
VMUSER=${VMUSER:-"ubuntu"}
476
NAME=${NAME:-"ubuntu"}
477
PASS=${PASS:-"ubuntu"}
481
if [ "$ARCH" = "lpia" ]
483
MIRROR="http://ports.ubuntu.com/ubuntu-ports"
485
MIRROR="http://archive.ubuntu.com/ubuntu"
488
if [ -z "$SECURITY_MIRROR" ]
490
if [ "$ARCH" = "lpia" ]
492
SECURITY_MIRROR="http://ports.ubuntu.com/ubuntu-ports"
494
SECURITY_MIRROR="http://security.ubuntu.com/ubuntu"
497
# save the mirror value for the source list if we are using --iso
501
VMHOSTNAME=${VMHOSTNAME:-"ubuntu-vm-$SUITE-$ARCH"}
502
DOMAIN=${DOMAIN:-"`hostname -d`"}
503
DOMAIN=${DOMAIN:-"localdomain"}
504
ROOTSIZE=${ROOTSIZE:-"4096"}
505
SWAPSIZE=${SWAPSIZE:-"1024"}
508
if [ "$KERNEL_FLAVOUR" = "virtual" ]
512
COMPS="main,restricted"
516
declare -a MOUNTPOINTS
517
declare -a MOUNTSIZES
518
declare -a MOUNTDISKS
521
declare -a PARTITION_START
522
declare -a PARTITION_END
528
echo "Excess option(s): $@"
532
# DISKIMGS holds the base names of the disk image files.
533
# LOOPDEV[i] holds the loop device name for disk image i
534
# MOUNTPOINTS[i] holds the mountpoint of partition i.
535
# MOUNTDISKS[i] holds
536
# MOUNTSIZES[i] holds the size of partition i.
542
letters=("a" "b" "c" "d")
545
if [ -z "$PARTFILE" ]; then
549
if [ $NUMRAW -gt 0 ]; then
550
DISKIMGS[0]=${RAW[0]}
552
DISKIMGS[0]="root.raw"
555
MOUNTPOINTS[$partid]="root"
556
MOUNTDISKS[$partid]="a"
557
MOUNTSIZES[$partid]="$ROOTSIZE"
558
let PARTITION_START[$partid]=$partstart
559
let PARTITION_END[$partid]=$partstart+MOUNTSIZES[$partid]
560
let partstart=PARTITION_END[$partid]+1
565
MOUNTPOINTS[$partid]="/opt"
566
MOUNTDISKS[$partid]="a"
567
MOUNTSIZES[$partid]="$OPTSIZE"
568
let PARTITION_START[$partid]=$partstart
569
let PARTITION_END[$partid]=$partstart+MOUNTSIZES[$partid]
570
let partstart=PARTITION_END[$partid]+1
574
MOUNTPOINTS[$partid]="swap"
575
MOUNTDISKS[$partid]="a"
576
if [ -z "$SWAPSIZE" ]; then
577
MOUNTSIZES[$partid]="1000"
579
MOUNTSIZES[$partid]="$SWAPSIZE"
581
let PARTITION_START[$partid]=$partstart
582
let PARTITION_END[$partid]=$partstart+MOUNTSIZES[$partid]
583
let DISKSIZES[0]=PARTITION_END[$partid]+1
590
echo "Disks and partitions:"
595
if [ "$line" = "---" ]; then
596
let DISKSIZES[$diskindex]=$partstart
597
let diskindex=$diskindex+1
600
if [ $diskindex -gt 3 ]; then
601
echo "Sorry, no more than 4 IDE disks..."
605
MOUNTDISKS[$index]="${letters[$diskindex]}"
606
MOUNTPOINTS[$index]=${line%\ *}
607
MOUNTSIZES[$index]=`echo "${line#*\ }" | sed 's/^[ \t]*//'`
608
let PARTITION_START[$index]=$partstart
609
let PARTITION_END[$index]=$partstart+MOUNTSIZES[$index]
610
if [ $partnum -eq 0 ]; then
611
if [ $NUMRAW -gt $diskindex ]; then
612
DISKIMGS[$diskindex]=${RAW[$diskindex]}
614
DISKIMGS[$diskindex]=`echo "${MOUNTPOINTS[$index]}" | sed 's%\/%%g' | sed 's/[ \t]*$//'`".raw"
616
info " Disk: $diskindex ${DISKIMGS[$diskindex]}"
619
info " Partition: $partnum ${MOUNTPOINTS[$index]} start: $partstart end: ${PARTITION_END[$index]} size: ${MOUNTSIZES[$index]}"
620
let partstart=PARTITION_END[$index]+1
622
let partnum=$partnum+1
626
let DISKSIZES[$diskindex]=$partstart
627
let NUMDISK=$diskindex
628
if [ $diskindex -gt $NUMRAW && $NUMRAW -gt 0 ]; then
629
echo "Sorry, --raw should match --part number of disks"
635
info "VMTMPDIR: $VMTMPDIR"
636
WORKINGDIR=$(mktemp -d -p $VMTMPDIR vm-builder-XXXXXXXXXX) || exit 1
638
if [ -z "$DESTINATION" ]
640
if [ -n "$VMHOSTNAME" ] && [ ! "$VMHOSTNAME" = "ubuntu-vm-$SUITE-$ARCH" ] ; then
641
DESTINATION="$PWD/ubuntu-vm-$SUITE-$ARCH-$VMHOSTNAME"
643
DESTINATION="$PWD/ubuntu-vm-$SUITE-$ARCH"
648
if [ -n "${SUDO_USER}" ]; then
649
sudo -u "${SUDO_USER}" mkdir "${DESTINATION}"
651
mkdir "${DESTINATION}"
654
if [ $? -ne 0 ]; then
655
if [ -z $OVERWRITE ]; then
656
echo "Error creating directory ${DESTINATION}. Unable to proceed."
657
rmdir "${WORKINGDIR}"
660
info "Overwriting content of ${DESTINATION}"
666
if [ -z "$IP" ]; then
669
if [ -z "$MASK" ]; then
671
echo "setting mask to \"$MASK\""
673
if [ -z "$NET" ]; then
674
NET=`echo $IP | sed 's/\./.0./3' | sed 's/\.[[:digit:]]\{1,3\}$//'`
675
echo "setting network to \"$NET\""
677
if [ -z "$BCAST" ]; then
678
BCAST=`echo $IP | sed 's/\./.255./3' | sed 's/\.[[:digit:]]\{1,3\}$//'`
679
echo "setting broadcast to \"$BCAST\""
681
if [ -z "$GW" ]; then
682
GW=`echo $IP | sed 's/\./.1./3' | sed 's/\.[[:digit:]]\{1,3\}$//'`
683
echo "setting gateway to \"$GW\""
685
if [ -z "$DNS" ]; then
686
DNS=`echo $IP | sed 's/\./.1./3' | sed 's/\.[[:digit:]]\{1,3\}$//'`
687
echo "setting name server to \"$DNS\""
695
# Set up a user with sudo etc.
698
chroot root adduser --disabled-password --gecos "${NAME}" ${VMUSER} > /dev/null
699
chroot root chpasswd <<EOF
703
chroot root addgroup --system admin >/dev/null 2>&1
704
chroot root adduser ${VMUSER} admin >/dev/null 2>&1
706
cat >> root/etc/sudoers << EOF
708
# Members of the admin group may gain root privileges
712
for group in adm audio cdrom dialout floppy video plugdev dip netdev powerdev lpadmin scanner; do
713
chroot root adduser ${VMUSER} $group >/dev/null 2>&1
717
chroot root chpasswd <<EOF
722
do_network_setup () {
723
echo $VMHOSTNAME > root/etc/hostname
725
cat > root/etc/hosts <<EOF
727
127.0.1.1 $VMHOSTNAME.$DOMAIN $VMHOSTNAME
729
# The following lines are desirable for IPv6 capable hosts
730
::1 ip6-localhost ip6-loopback
732
ff00::0 ip6-mcastprefix
734
ff02::2 ip6-allrouters
738
cat > root/etc/network/interfaces <<EOF
739
# This file describes the network interfaces available on your system
740
# and how to activate them. For more information, see interfaces(5).
742
# The loopback network interface
744
iface lo inet loopback
746
# The primary network interface
749
if [ "$IP" = "DHCP" ]; then
750
cat >> root/etc/network/interfaces <<EOF
754
cat >> root/etc/network/interfaces <<EOF
755
iface eth0 inet static
761
# dns-* options are implemented by the resolvconf package, if installed
767
#temporary fix for /var/run/network not being created
768
if [ ! -e root/var/run/network ]; then
769
echo "Creating /var/run/network"
770
mkdir root/var/run/network
774
do_kernel_img_conf () {
776
cat > root/etc/kernel-img.conf << EOF
789
# The suite will have defined updategrub
791
sed -e "s,%UPDATEGRUB%,$updategrub,g" << EOF | cat >> target/etc/kernel-img.conf
792
postinst_hook = %UPDATEGRUB%
793
postrm_hook = %UPDATEGRUB%
795
chroot target apt-get --force-yes -y install grub
797
mkdir target/boot/grub
799
if [ $ARCH = "amd64" ]
805
cp target/$grubroot/$grubarch/* target/boot/grub/
810
echo "(hd0) ${DISKIMGS[0]}" >> device.map
811
grub --device-map=device.map --batch<<EOT
816
cat > target/boot/grub/device.map << EOF
819
suite_generate_device_map
821
# Hacky-di-hack.. First generate the template, then remove the errant kopt_2_6 (which hardcodes the root device to /dev/hda1) and then rerun update-grub.
822
chroot target $updategrub -y
823
suite_mangle_grub_menu_lst
824
chroot target $updategrub
825
chroot target grub-set-default 0
829
info "do_disk_images"
831
# Create disk images, partitions and format
834
for ((i=0; i<${#DISKIMGS[@]}; i++)); do
835
if [ $NUMRAW -eq 0 ]; then
837
let size=${DISKSIZES[$i]}*1024
838
qemu-img create -f raw ${DISKIMGS[$i]} $size > /dev/null
842
parted --script ${DISKIMGS[$i]} mklabel msdos
848
# create the partitions
849
for ((i=0;i<${#MOUNTPOINTS[@]};i++)); do
850
if [ "$curdisk" != "${MOUNTDISKS[$i]}" ]; then
852
img="${DISKIMGS[$diskindex]}"
853
curdisk=${MOUNTDISKS[$i]}
854
info "Disk: $curdisk $img"
857
# Create partition and format
858
info " creating partition ${MOUNTPOINTS[$i]} on $img"
859
if [ "${MOUNTPOINTS[$i]}" = "swap" ]; then
860
parted --script -- $img mkpartfs primary linux-swap ${PARTITION_START[$i]} ${PARTITION_END[$i]}
862
parted --script -- $img mkpartfs primary ext2 ${PARTITION_START[$i]} ${PARTITION_END[$i]}
866
#mount the disk loops
867
for ((i=0;i<${#DISKIMGS[@]};i++)); do
868
LOOPDEV[$i]=$(losetup -s -f ${DISKIMGS[$i]})
869
kpartx -a ${LOOPDEV[$i]} > /dev/null
872
#format the partitions
875
for ((i=0;i<${#MOUNTPOINTS[@]};i++)); do
876
if [ "$curdisk" != "${MOUNTDISKS[$i]}" ]; then
877
let diskindex++ || true
878
img="${DISKIMGS[$diskindex]}"
879
curdisk=${MOUNTDISKS[$i]}
881
mapper=$(echo ${LOOPDEV[$diskindex]} | sed s-/dev/-/dev/mapper/-)
884
if [ "${MOUNTPOINTS[$i]}" = "swap" ]; then
885
info formating ${mapper}p${partindex} as swap for ${MOUNTPOINTS[$i]}
886
mkswap ${mapper}p${partindex}
888
info formating ${mapper}p${partindex} as ext3 for ${MOUNTPOINTS[$i]}
889
mkfs.ext3 -q ${mapper}p${partindex}
891
/lib/udev/vol_id --uuid ${mapper}p${partindex} > ${MOUNTPOINTS[$i]}.uuid
897
info "do_source $1 $2, iso: $ISO"
898
if [ -n "$ISO" ]; then
899
# source is an ISO file
900
if [ -e "$ISO" ]; then
903
# this is not the first time: need to unmount the previous first
904
umount $2/isomnt || true
906
MIRROR="file:///isomnt"
908
MIRROR="file://$1/isomnt"
910
if [ ! "$1" = "-" ]; then
911
# we have something to mount
913
mount -o loop -t iso9660 $ISO $1/isomnt
917
echo "$ISO not found, using $MIRROR"
921
# this is not the first time, update the source.list on the target
922
if [ "$1" = "-" ]; then
923
# this the last time we are called, push the --mirror info
924
do_sourceslist $ORIGMIRROR $SECURITY_MIRROR $2
926
do_sourceslist $MIRROR $SECURITY_MIRROR $1
929
sudo chroot $1 apt-get update &> /dev/null || true
935
if [ -n "$INSTALL_IN_PLACE" ]
939
mkdir root &> /dev/null || true
942
debootstrap --components="$COMPS" --arch $ARCH --keyring /usr/share/keyrings/ubuntu-archive-keyring.gpg $SUITE root "$MIRROR"
945
do_kernel_n_friends () {
946
info "kernel_n_friends"
947
PKGS="linux-$KERNEL_FLAVOUR"
950
chroot root apt-get -o APT::Install-Recommends=False --force-yes -y install $PKGS
953
do_add_remove_packages () {
954
info "add_remove_packages"
955
cmd="apt-get --purge install "
956
chroot root apt-get -y --force-yes --purge install $PKGCMD || true
962
test -z "$SSHKEY" && test -z "$SSHUKEY" && return
966
cp "$SSHKEY" root/root/.ssh/authorized_keys
967
chroot root chown -R root:root /root/.ssh
970
test -n "$SSHKEY" && echo "No ssh root key found: $SSHKEY"
974
mkdir root/home/$VMUSER/.ssh
975
cp "$SSHUKEY" root/home/$VMUSER/.ssh/authorized_keys
976
chroot root chown -R $VMUSER:$VMUSER /home/$VMUSER/.ssh
979
test -n "$SSHUKEY" && echo "No ssh user key found: $SSHUKEY"
981
if [ -n "$sshinstalled" ]; then
982
chroot root apt-get install --force-yes -y openssh-server || true
989
info "sourceslists $1 $2 $3"
990
cat > $3/etc/apt/sources.list << EOF
991
deb $1 ${SUITE} main restricted
992
#deb-src $1 ${SUITE} main restricted
994
## Major bug fix updates produced after the final release of the
996
deb $1 ${SUITE}-updates main restricted
997
#deb-src $1 ${SUITE}-updates main restricted
999
deb $2 ${SUITE}-security main restricted
1000
#deb-src $2 ${SUITE}-security main restricted
1004
if echo $COMPS | grep universe &> /dev/null
1006
cat >> $3/etc/apt/sources.list << EOF
1007
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
1008
## team, and may not be under a free licence. Please satisfy yourself as to
1009
## your rights to use the software. Also, please note that software in
1010
## universe WILL NOT receive any review or updates from the Ubuntu security
1012
deb $1 ${SUITE} universe
1013
#deb-src $1 ${SUITE} universe
1014
deb $1 ${SUITE}-updates universe
1015
#deb-src $1 ${SUITE}-updates universe
1016
deb $2 ${SUITE}-security universe
1017
#deb-src $2 ${SUITE}-security universe
1020
cat >> $3/etc/apt/sources.list << EOF
1021
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
1022
## team, and may not be under a free licence. Please satisfy yourself as to
1023
## your rights to use the software. Also, please note that software in
1024
## universe WILL NOT receive any review or updates from the Ubuntu security
1026
#deb $1 ${SUITE} universe
1027
#deb-src $1 ${SUITE} universe
1028
#deb $1 ${SUITE}-updates universe
1029
#deb-src $1 ${SUITE}-updates universe
1030
#deb $2 ${SUITE}-security universe
1031
#deb-src $2 ${SUITE}-security universe
1037
if echo $COMPS | grep multiverse &> /dev/null
1039
cat >> $3/etc/apt/sources.list << EOF
1040
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
1041
## team, and may not be under a free licence. Please satisfy yourself as to
1042
## your rights to use the software. Also, please note that software in
1043
## multiverse WILL NOT receive any review or updates from the Ubuntu
1045
deb $1 ${SUITE} multiverse
1046
#deb-src $1 ${SUITE} multiverse
1047
deb $1 ${SUITE}-updates multiverse
1048
#deb-src $1 ${SUITE}-updates multiverse
1049
deb $2 ${SUITE}-security multiverse
1050
#deb-src $2 ${SUITE}-security multiverse
1053
cat >> $3/etc/apt/sources.list << EOF
1054
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
1055
## team, and may not be under a free licence. Please satisfy yourself as to
1056
## your rights to use the software. Also, please note that software in
1057
## multiverse WILL NOT receive any review or updates from the Ubuntu
1059
#deb $1 ${SUITE} multiverse
1060
#deb-src $1 ${SUITE} multiverse
1061
#deb $1 ${SUITE}-updates multiverse
1062
#deb-src $1 ${SUITE}-updates multiverse
1063
#deb $2 ${SUITE}-security multiverse
1064
#deb-src $2 ${SUITE}-security multiverse
1067
cat >> $3/etc/apt/sources.list << EOF
1068
## Uncomment the following two lines to add software from the 'backports'
1070
## N.B. software from this repository may not have been tested as
1071
## extensively as that contained in the main release, although it includes
1072
## newer versions of some applications which may provide useful features.
1073
## Also, please note that software in backports WILL NOT receive any review
1074
## or updates from the Ubuntu security team.
1075
# deb $1 ${SUITE}-backports main restricted universe multiverse
1076
# deb-src $1 ${SUITE}-backports main restricted universe multiverse
1078
## Uncomment the following two lines to add software from Canonical's
1079
## 'partner' repository. This software is not part of Ubuntu, but is
1080
## offered by Canonical and the respective vendors as a service to Ubuntu
1082
# deb http://archive.canonical.com/ubuntu hardy partner
1083
# deb-src http://archive.canonical.com/ubuntu hardy partner
1087
do_copy_settings () {
1088
info "do_copy_settings"
1089
#copy the host settings to the new guest (locale, console-setup, tz)
1090
cp /etc/default/locale root/etc/default/
1091
cp -a /etc/console-setup root/etc/
1092
cp /etc/default/console-setup root/etc/default/
1093
cp /etc/timezone root/etc/
1094
chroot root dpkg-reconfigure -pcritical tzdata
1096
chroot root locale-gen en_US
1097
chroot root locale-gen $LANG
1098
chroot root dpkg-reconfigure -pcritical locales
1099
chroot root dpkg-reconfigure -pcritical console-setup
1100
info "do_copy_settings done"
1112
# Execute the script.
1114
info "Executing $EXEC"
1116
echo "Error executing user defined script"
1124
if [ -z "$FIRSTBOOT" ]; then
1126
elif [ ! -f "$FIRSTBOOT" ]; then
1127
echo "Script '$FIRSTBOOT' not found."
1131
# Install the script to be executed
1133
cp $FIRSTBOOT root/root/firstboot.sh
1134
chmod a+x root/root/firstboot.sh
1135
mv root/etc/rc.local root/etc/rc.local.orig
1136
cat > root/etc/rc.local <<EOT
1138
#execute firstboot.sh only once
1139
if [ ! -e /root/firstboot_done ]; then
1140
if [ -e /root/firstboot.sh ]; then
1143
touch /root/firstboot_done
1147
chmod a+x root/etc/rc.local
1153
if [ -z "$FIRSTLOGIN" ]; then
1155
elif [ ! -f "$FIRSTLOGIN" ]; then
1156
echo "Script '$FIRSTLOGIN' not found."
1160
# Install the script to be executed
1162
if [ -n "$dofirst" ]; then
1163
cp $FIRSTLOGIN root/root/firstlogin.sh
1164
chmot a+x root/root/firstlogin.sh
1166
cp root/etc/bash.bashrc root/etc/bash.bashrc.orig
1167
cat >> root/etc/bash.bashrc <<EOT
1168
if [ ! -e /root/firstlogin_done ]; then
1169
if [ -e /root/firstlogin.sh ]; then
1172
# This part should not be necessary any more
1173
#echo "Setting up your keyboard, will need sudo password."
1174
#sudo dpkg-reconfigure -p critical console-setup &> /dev/null
1175
sudo touch /root/firstlogin_done
1183
if [ "$base" = "" ]; then
1184
echo base is empty.... exiting
1189
for ((i=0;i<${#MOUNTPOINTS[@]};i++)); do
1190
if [ "$curdisk" != "${MOUNTDISKS[$i]}" ]; then
1192
img="${DISKIMGS[$diskindex]}"
1193
curdisk=${MOUNTDISKS[$i]}
1195
mapper=$(echo ${LOOPDEV[$diskindex]} | sed s-/dev/-/dev/mapper/-)
1198
if [ "${MOUNTPOINTS[$i]}" = "root" ]; then
1199
mount ${mapper}p${partindex} $base
1200
elif [ "${MOUNTPOINTS[$i]}" != "swap" ]; then
1201
mkdir $base${MOUNTPOINTS[$i]}
1202
mount ${mapper}p${partindex} $base${MOUNTPOINTS[$i]}
1211
for ((i=$(( ${#MOUNTPOINTS[@]} -1));i>-1;i--)); do
1212
if [ "${MOUNTPOINTS[$i]}" = "root" ]; then
1215
elif [ "${MOUNTPOINTS[$i]}" != "swap" ]; then
1216
echo umount $base${MOUNTPOINTS[$i]}
1217
umount $base${MOUNTPOINTS[$i]}
1222
# Taken from debootstrap
1223
do_avoid_starting_daemons() {
1224
info "avoid_starting_daemons"
1225
cat > root/usr/sbin/policy-rc.d <<EOT
1232
x11-common) exit 0;;
1237
chmod 755 "root/usr/sbin/policy-rc.d"
1241
# Taken from debootstrap
1242
do_undo_avoid_starting_daemons() {
1243
info "undo_avoid_starting_daemons"
1244
rm root/usr/sbin/policy-rc.d
1248
# linux-restricted-modules unconditionally mounts a tmpfs.
1250
do_unmount_restricted_tmpfs() {
1251
info "unmount_restriced_tmpfs"
1252
umount root/lib/modules/*/volatile > /dev/null 2>&1 || true
1261
do_umount_target() {
1262
info "unmount_target"
1267
do_copy_to_disk_images () {
1268
chroot root apt-get clean
1269
if [ -e root/isomnt ]; then
1272
if [ -z "$INSTALL_IN_PLACE" ]
1275
# Copy the debootstrapped filesystem into the partitions
1277
info Copy the debootstrapped filesystem
1284
do_target_vm_conversion () {
1285
info Convert to format $VM
1287
vm_target_conversion
1289
#do image conversion if not asked to do raw images
1290
if [ $NUMRAW -eq 0 ]; then
1291
for ((i=0;i<${#DISKIMGS[@]};i++)); do
1292
img=$( echo ${DISKIMGS[$i]} | sed s/.raw// )
1293
qemu-img convert $QEMU_IMG_CONVERT_OPTS ${DISKIMGS[$i]} "$img${QEMU_IMG_CONVERT_EXTENSION}"
1296
test -n "${SUDO_USER}" && chown "$SUDO_USER" $FILES
1297
mv $FILES $DESTINATION
1298
echo "Done. Images are in ${DESTINATION}."
1300
echo "Done, raw images/devices ready."
1306
info "Cleaning up..."
1307
if [ -n "$VERBOSE" ]; then
1308
echo "Press return to go ahead with cleanup"
1311
#unmount iso if present
1312
if [ -e $WORKINGDIR/isomnt ]; then
1313
umount $WORKINGDIR/isomnt
1314
elif [ -e $WORKINGDIR/target/isomnt ]; then
1315
umount $WORKINGDIR/target/isomnt
1316
elif [ -e $WORKINGDIR/root/isomnt ]; then
1317
umount $WORKINGDIR/root/isomnt
1320
#umount target if present
1321
if [ -e target ]; then
1325
#unmount the disk loops
1326
for ((i=0;i<${#DISKIMGS[@]};i++)); do
1327
kpartx -d ${LOOPDEV[$i]} > /dev/null
1328
losetup -d ${LOOPDEV[$i]}
1332
for ((i=0;i<${#MOUNTPOINTS[@]};i++)); do
1333
rm ${MOUNTPOINTS[$i]}.uuid
1336
if [ $NUMRAW -eq 0 ]; then
1338
for ((i=0;i<${#DISKIMGS[@]};i++)); do
1346
#unmount and remove working directory
1347
if [ -n "$TMPFS" ]; then
1348
umount "$WORKINGDIR"
1350
rm -rf "$WORKINGDIR"
1353
function errorHandler () {
1359
function interruptHandler () {
1360
echo "User interupt"
1365
if [ -n "$TMPFS" ]; then
1366
if [ "$TMPFS" = "-" ]; then
1367
mount -t tmpfs ubuntu-vm-builder -o suid,dev,size=1G "$WORKINGDIR"
1369
mount -t tmpfs ubuntu-vm-builder -o $TMPFS "$WORKINGDIR"
1372
info "Working in $WORKINGDIR"
1373
pushd "$WORKINGDIR" > /dev/null
1376
set +e; trap errorHandler ERR
1377
trap interruptHandler SIGINT SIGTERM
1378
do_source $WORKINGDIR ""
1382
do_avoid_starting_daemons
1386
do_source "root" $WORKINGDIR
1389
do_add_remove_packages
1394
do_undo_avoid_starting_daemons
1395
do_unmount_restricted_tmpfs
1396
do_copy_to_disk_images
1397
do_source "target" "root"
1399
do_source "-" "target"
1401
do_target_vm_conversion