Created
January 14, 2012 19:44
-
-
Save NaPs/1612654 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Create and spawn a new virtual machine with Debian Squeeze | |
# | |
# | |
# Configuration: | |
DEFAULT_STORAGE="storage" | |
DEFAULT_BRIDGE="internet" | |
DEFAULT_MEMORY=128 | |
DEFAULT_DISK=1 | |
DEFAULT_VCPU=1 | |
MOUNT_POINT="/mnt/vm" | |
PACKAGES="linux-image-2.6-amd64,openssh-server,grub2" | |
# End of Configuration. | |
usage () { | |
echo "Usage: $0 [-mdvdgbpw] name ip-address" | |
echo "" | |
echo " -h show this help" | |
echo " -m MEMORY amound of RAM memory of the VM (in MegaBytes)" | |
echo " -v VCPU number of virtual CPU affected to the VM" | |
echo " -d DISK amound of disk size of the VM (in GigaBytes)" | |
echo " -g VG LVM Virtual Group to use" | |
echo " -b BRIDGE network bridge to use" | |
echo " -p SOME,PACK,AGES additional packages to install" | |
echo " -w ask for the root password" | |
echo " -t tecknetify" | |
echo "" | |
} | |
check () { | |
if [ $? != 0 ]; then | |
echo "### Step: error while $1 (err: $?)" | |
exit 2 | |
else | |
echo "### Step: $1 OK" | |
fi | |
} | |
create_vm () { | |
# $1: vm name | |
# $2: memory size | |
# $3: vcpu number | |
# $4: storage name | |
# $5: volume size | |
# $6: network bridge | |
# Create the volume: | |
virsh vol-create-as $4 $1 ${5}G | |
check "volume creation" | |
virt-install --name $1 --ram $2 --vcpus $3 --import --os-type=linux --os-variant=virtio26 --disk vol="$4/$1" --network bridge=$6 --noreboot --vnc | |
check "vm define" | |
} | |
partition_disk () { | |
# $1: path to disk | |
parted --script $1 mklabel gpt | |
check "partition table creation" | |
parted --script $1 mkpart primary ext4 2048s 8191s | |
check "partition bios_grub creation" | |
parted --script $1 set 1 bios_grub on | |
check "partition bios_grub settings" | |
parted --script $1 "mkpart primary ext4 8192s -1" | |
check "partition root creation" | |
sleep 3 | |
kpartx $1 | |
check "partition probbing" | |
sleep 3 | |
} | |
format_disk () { | |
# $1: path to disk | |
mkfs.ext4 -L root "$1" | |
check "disk formatage" | |
} | |
mount_disk () { | |
# $1: path to part | |
mkdir -p $MOUNT_POINT | |
mount -t ext4 $1 $MOUNT_POINT | |
check "disk mount" | |
} | |
umount_disk () { | |
# $1: path to disk | |
# $1: path to part | |
umount $2 | |
check "disk mount" | |
kpartx -d $1 | |
check "partitions unregister" | |
} | |
install_system () { | |
# $1: packages to install | |
cdebootstrap --arch amd64 --include "$1" squeeze $MOUNT_POINT http://ftp.fr.debian.org/debian/ | |
check "debian debootstrap" | |
} | |
mount_utils () { | |
mount -o bind /proc $MOUNT_POINT/proc | |
check "/proc mount" | |
mount -o bind /dev $MOUNT_POINT/dev | |
check "/dev mount" | |
mount -o bind /sys $MOUNT_POINT/sys | |
check "/sys mount" | |
} | |
umount_utils () { | |
umount $MOUNT_POINT/proc | |
check "/proc umount" | |
umount $MOUNT_POINT/dev | |
check "/dev umount" | |
umount $MOUNT_POINT/sys | |
check "/sys umount" | |
} | |
generate_configuration () { | |
# $1: vm name | |
# $2: part path | |
# $3: ip address | |
uuid=blkid -o value -s UUID $2 | |
cat > "$MOUNT_POINT/etc/fstab" <<END | |
proc /proc proc defaults 0 0 | |
UUID=$uuid / ext4 noatime,errors=remount-ro 0 1 | |
END | |
check "/etc/fstab" | |
cat > "$MOUNT_POINT/etc/network/interfaces" <<END | |
auto lo | |
iface lo inet loopback | |
allow-hotplug eth0 | |
iface eth0 inet static | |
address $3 | |
netmask 255.255.255.255 | |
up /sbin/route add -host 88.190.13.1 dev eth0 | |
up /sbin/route add default gw 88.190.13.1 | |
END | |
check "/etc/network/interfaces" | |
echo $1 > "$MOUNT_POINT/etc/hostname" | |
check "/etc/hostname" | |
cat > "$MOUNT_POINT/etc/hosts" <<END | |
127.0.0.1 localhost $1.tecknet.org $1 | |
# The following lines are desirable for IPv6 capable hosts | |
::1 localhost ip6-localhost ip6-loopback | |
fe00::0 ip6-localnet | |
ff00::0 ip6-mcastprefix | |
ff02::1 ip6-allnodes | |
ff02::2 ip6-allrouters | |
END | |
check "/etc/hosts" | |
rm -f "$MOUNT_POINT/etc/udev/rules.d/70-persistent-net.rules" | |
check "rm /etc/udev/rules.d/70-persistent-net.rules" | |
} | |
tecknetize () { | |
cat > "$MOUNT_POINT/etc/profile" <<"END" | |
# /etc/profile - Tecknet | |
# path | |
if [ "`id -u`" -eq 0 ]; then | |
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" | |
else | |
PATH="/usr/local/bin:/usr/bin:/bin:/usr/games" | |
fi | |
export PATH | |
# Umask | |
umask 022 | |
# Load specific shell settings | |
shell="sh" | |
if test -f /proc/mounts; then | |
case $(/bin/ls -l /proc/$$/exe) in | |
*bash) shell=bash ;; | |
*dash) shell=dash ;; | |
*ash) shell=ash ;; | |
*ksh) shell=ksh ;; | |
*zsh) shell=zsh ;; | |
esac | |
fi | |
test -f "/etc/profile.$shell" && . "/etc/profile.$shell" | |
# Some readline stuff that is fairly common | |
HISTSIZE=1000 | |
HISTCONTROL="erasedups" | |
INPUTRC="/etc/inputrc" | |
LESS="-R" | |
LC_COLLATE="C" | |
# Termcap is outdated, old, and crusty, kill it. | |
unset TERMCAP | |
# Man is much better than us at figuring this out | |
unset MANPATH | |
# Aliases | |
export LS_OPTIONS='--color=auto' | |
eval "`dircolors`" | |
alias ls='ls $LS_OPTIONS' | |
alias ll='ls $LS_OPTIONS -l' | |
alias l='ls $LS_OPTIONS -lA' | |
alias sr='ssh -l root' | |
END | |
cat > "$MOUNT_POINT/etc/profile.bash" <<"END" | |
# /etc/profile.bash - Tecknet | |
# Prompt: | |
export PROMPT_COMMAND='PS1="\`if [[ \$? = "0" ]]; then echo "\\[\\033[33m\\]"; else echo "\\[\\033[1\\\;31m\\]!"; fi\`\[\033[0;33m\]\`date +%H%M\` [\`if [[ \$UID = "0" ]]; then echo "\\[\\033[0\\\;31m\\]"; else echo "\\[\\033[0\\\;32m\\]\\u@"; fi\`\h:\w\[\033[33m\]]\\$\[\033[0m\] ";' | |
END | |
cat > "$MOUNT_POINT/etc/motd.tail" <<END | |
_______ _ _ | |
|__ __| | | | | | |
| | ___ ___| | ___ __ ___| |_ | |
| |/ _ \/ __| |/ / '_ \ / _ \ __| | |
| | __/ (__| <| | | | __/ |_ | |
|_|\___|\___|_|\_\_| |_|\___|\__| | |
END | |
cat "$MOUNT_POINT/etc/motd.tail" > "$MOUNT_POINT/etc/motd" | |
# Setup /etc/issue.net | |
echo "I think you ought to know I'm feeling very depressed." > "$MOUNT_POINT/etc/issue.net" | |
echo "Banner /etc/issue.net" >> "$MOUNT_POINT/etc/ssh/sshd_config" | |
mkdir -p /root/.ssh | |
echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqnTT5rte4rjDMZwsTv3TqlpofpoQg0yifsb3pPbZuN8zqJzzqkuyPQni68hb2OvlRNzsjwJ6WRyqMtQ2R0d/6WyN+9PMg+sbFobYpLx4cMddV4A04KAkrGU0ncnXAP1a6xif3qh/Sm+cW0GnziKaYfaBkKE8YmH9r+G9s1D+EVYqptqtn9QoZIgMBccFlPIgKACkcgGUCEYAAB9DQMYIyf4WJnHSSFilGHa5v/Mu3tcA2LHuvIs6n85lTyIVf/g0//mzk7DQAWN2FR3+xBORVJHbcz0Wu1qYP2mBsWQ49kmcCNwNCO5dwMUqpc1sDsbX8Ro/xrflH7+oTgjTV6x7cw== Antoine" >> /root/.ssh/authorized_keys | |
} | |
install_grub () { | |
# $1: disk path | |
# $2: part path | |
mv "$MOUNT_POINT/usr/sbin/grub-probe" "$MOUNT_POINT/usr/sbin/grub-probe_real" | |
cat > "$MOUNT_POINT/usr/sbin/grub-probe" <<END | |
#!/bin/bash | |
if [ "\$2" == "--target=device" ]; then | |
echo $1 | |
fi | |
if [ "\$2" == "--target=fs" ]; then | |
echo ext2 | |
fi | |
if [ "\$1" == "--target=device" ]; then | |
echo /dev/vda2 | |
fi | |
if [ "\$1" == "--device" ]; then | |
blkid -o value -s UUID $2 | |
fi | |
END | |
chmod +x "$MOUNT_POINT/usr/sbin/grub-probe" | |
echo "(hd0) /dev/vda" > "$MOUNT_POINT/boot/grub/device.map" | |
chroot $MOUNT_POINT grub-install --no-floppy --modules="part_gpt ext2" --grub-setup=/bin/true /dev/vda | |
check "grub-install" | |
tmp_devmap="$MOUNT_POINT/tmp/device.map" | |
echo "(hd0) $1" > $tmp_devmap | |
chroot $MOUNT_POINT grub-setup --verbose --force --skip-fs-probe --device-map=/tmp/device.map --root-device='(hd0,2)' '(hd0)' | |
check "grub-setup" | |
chroot $MOUNT_POINT grub-mkconfig -o /boot/grub/grub.cfg | |
check "grub-mkconfig" | |
mv "$MOUNT_POINT/usr/sbin/grub-probe_real" "$MOUNT_POINT/usr/sbin/grub-probe" | |
} | |
ask_root_password () { | |
chroot $MOUNT_POINT passwd | |
} | |
vm_memory=$DEFAULT_MEMORY | |
vm_disk=$DEFAULT_DISK | |
vm_vcpu=$DEFAULT_VCPU | |
vm_bridge=$DEFAULT_BRIDGE | |
storage=$DEFAULT_STORAGE | |
packages=$PACKAGES | |
ask_passwd=false | |
tecknetify=false | |
while getopts "hm:v:d:g:b:p:wt" opt; do | |
case $opt in | |
h) usage; exit ;; | |
m) vm_memory=$OPTARG ;; | |
v) vm_vcpu=$OPTARG ;; | |
d) vm_disk=$OPTARG ;; | |
g) storage=$OPTARG ;; | |
b) bridge=$OPTARG ;; | |
p) packages="$packages,$OPTARG" ;; | |
w) ask_passwd="true" ;; | |
t) tecknetify="true" ;; | |
?) echo "Bad option -$OPTARG" && exit 1 ;; | |
:) echo "-$OPTARG requires an argument" && exit 1 ;; | |
esac | |
done | |
shift $(($OPTIND - 1)) | |
vm_name=$1 | |
vm_ipaddress=$2 | |
if [ "$vm_name" == "" ]; then | |
if [ "$vm_ipaddress" == "" ]; then | |
usage; | |
exit 1 | |
fi | |
fi | |
create_vm $vm_name $vm_memory $vm_vcpu $storage $vm_disk $vm_bridge | |
sleep 3 | |
# Get the path to volume: | |
vm_disk_path=`virsh vol-path --pool $storage $vm_name` | |
vm_disk_part="/dev/mapper/${storage}-${vm_name}p2" | |
partition_disk $vm_disk_path | |
format_disk $vm_disk_part | |
mount_disk $vm_disk_part | |
install_system $PACKAGES | |
mount_utils | |
generate_configuration $vm_name $vm_disk_part $vm_ipaddress | |
if [ "$tecknetify" == "true" ]; then | |
tecknetize | |
fi | |
install_grub $vm_disk_path $vm_disk_part | |
if [ "$ask_passwd" == "true" ]; then | |
ask_root_password | |
fi | |
umount_utils | |
umount_disk $vm_disk_path $vm_disk_part |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment