Skip to content

Instantly share code, notes, and snippets.

@NaPs
Created January 14, 2012 19:44
Show Gist options
  • Save NaPs/1612654 to your computer and use it in GitHub Desktop.
Save NaPs/1612654 to your computer and use it in GitHub Desktop.
#!/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