From 41599461aa00610e1842fc72d8ac99812ace2edf Mon Sep 17 00:00:00 2001 From: Peter Palfrader Date: Wed, 18 Feb 2015 15:38:15 +0100 Subject: Add install-VM-grongo --- install-VM-grongo | 417 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100755 install-VM-grongo (limited to 'install-VM-grongo') diff --git a/install-VM-grongo b/install-VM-grongo new file mode 100755 index 0000000..f3599e0 --- /dev/null +++ b/install-VM-grongo @@ -0,0 +1,417 @@ +#!/bin/bash + +# create a VM image using debootstrap +# +# Copyright 2013, 2014, 2015 Peter Palfrader +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You probably already have access to a copy of the GNU General Public +# License or you can find one on the Internet; if not, write to the +# copyright holder or to the Free Software Foundation, Inc., 59 Temple +# Place, Suite 330, Boston, MA 02111-1307 USA. + +set -e +set -u + +SUITE=jessie +hostlistfile=/root/VMs/host-list + +MIRROR=http://ftp.at.debian.org/debian +prefixlen=26 +gateway=213.235.231.193 +ip6prefix=2001:858:10f:100:: +ip6gateway=fe80:: +basedir=/srv/vmstore + +check_installed() { + local p + for p in "$@"; do + if ! dpkg -l "$p" 2>/dev/null | grep -q '^ii'; then + echo >&2 "Error: package $p not installed:" + echo >&2 " apt-get install $*" + exit 1 + fi + done +} +get_sshkey_fprs() { + local f + for f in etc/ssh/ssh_host*_key.pub; do + echo -n " " + ssh-keygen -l -f "$f" + done +} + +do_cleanup() { + #echo "Proposed cleanup:" + local cnt + cnt=$((${#cleanup[*]}-1)) + #for i in $(seq ${cnt} -1 0); do + # echo " ${cleanup[$i]}" + #done + #echo "Press enter to commence cleanup." + #read + for i in $(seq ${cnt} -1 0); do + echo "* ${cleanup[$i]}" + eval "${cleanup[$i]}" || true + done + echo "done." +} + +check_installed debootstrap debian-archive-keyring kpartx + +declare -a cleanup +cleanup+=(":") +trap do_cleanup EXIT + +echo -n "New VM's FQDN: " +if [ -n "${1:-}" ]; then echo "$1"; fqdn="$1"; shift; else read fqdn; fi +echo +guest="${fqdn%%.*}" +domainname="${fqdn#*.}" + +echo -n "Disk size: [10g]" +if [ -n "${1:-}" ]; then echo "$1"; disksize="$1"; shift; else read disksize; fi +disksize=${disksize:-10g} + +echo -n "Swap size: [4g]" +if [ -n "${1:-}" ]; then echo "$1"; swapsize="$1"; shift; else read swapsize; fi +swapsize=${swapsize:-4g} + +echo -n "Lvm size: [20g]" +if [ -n "${1:-}" ]; then echo "$1"; lvmsize="$1"; shift; else read lvmsize; fi +lvmsize=${lvmsize:-20g} +if [ "$lvmsize" = "0" ]; then lvmsize=""; fi + +echo -n "ipaddr: "; +if [ -n "${1:-}" ]; then echo "$1"; ipaddr="$1"; shift; else read ipaddr; fi + +echo -n "unique hostno (2-254): "; +if [ -n "${1:-}" ]; then echo "$1"; hostno="$1"; shift; else read hostno; fi + +if awk -v v="$hostno" '$1 == v {print}' "$hostlistfile" | grep .; then + echo >&2 "Host number $hostno already used in $hostlistfile." + exit 1 +fi +if awk -v v="$ipaddr" '$2 == v {print}' "$hostlistfile" | grep .; then + echo >&2 "IP address $ipaddr already used in $hostlistfile." + exit 1 +fi +if awk -v v="$fqdn" '$3 == v {print}' "$hostlistfile" | grep .; then + echo >&2 "FQDN $fqdn already used in $hostlistfile." + exit 1 +fi + +diskfileprefix="$basedir/$fqdn/" +if [ -e "$diskfileprefix" ]; then + echo >&2 "Error: Disk directory $diskfileprefix already exists." + exit 1 +fi + +target="/mnt/target-$guest" +if [ -e "$target" ]; then + echo >&2 "Error: Directory $target already exists." + exit 1 +fi + + +diskfileroot="${diskfileprefix}$guest-root" +diskfileswap="${diskfileprefix}$guest-swap" +diskfilelvm="${diskfileprefix}$guest-lvm" + +mkdir "$diskfileprefix" +(umask 077 && qemu-img create -f qcow2 "$diskfileroot" "$disksize") +(umask 077 && qemu-img create -f raw "$diskfileswap" "$swapsize") +if [ "$lvmsize" != "" ] ; then + (umask 077 && qemu-img create -f qcow2 "$diskfilelvm" "$lvmsize") +fi + +modprobe nbd max_part=63 + +rootdev=/dev/nbd0 +lvmdev=/dev/nbd1 + +qemu-nbd -c "$rootdev" "$diskfileroot" +cleanup+=("qemu-nbd -d '$rootdev'") + +if [ "$lvmsize" != "" ] ; then + qemu-nbd -c "$lvmdev" "$diskfilelvm" + cleanup+=("qemu-nbd -d '$lvmdev'") +fi + +if [ "$(head -c 65536 "$rootdev" | sha1sum | awk '{print $1}')" != "1adc95bebe9eea8c112d40cd04ab7a8d75c4f961" ]; then + echo -n "Warning: Disk appears to be not be empty. Continue anyway? [y/N] " + read ans + [ "$ans" = "y" ] || exit 0 +fi + +ip6addr="$ip6prefix$hostno:1" + +echo '2048,,L,*' | sfdisk -u S --Linux "$rootdev" +kpartx -v -p "-p" -a "$rootdev" -s +cleanup+=("kpartx -d -p '-p' -v '$rootdev'") +part1="/dev/mapper/$(basename $rootdev)-p1" +mkfs.ext4 "$part1" + +if [ "$lvmsize" != "" ] ; then + pvcreate "$lvmdev" + vgcreate "vg_$guest" "$lvmdev" +fi + +mkdir "$target" +cleanup+=("rmdir '$target'") +mount "$part1" "$target" +cleanup+=("umount '$target'") +cd "$target" +cleanup+=("cd /") + +debootstrap --variant=minbase --keyring=/usr/share/keyrings/debian-archive-keyring.gpg "$SUITE" . "$MIRROR" + +### Set up swap and fstab +mkswap "$diskfileswap" + +uuidroot=$(blkid -s UUID -o value ${part1}) && +uuidswap=$(blkid -s UUID -o value $diskfileswap) && +cat > etc/fstab << EOF +UUID=$uuidroot / ext4 errors=remount-ro 0 1 +UUID=$uuidswap none swap sw 0 0 +tmpfs /tmp tmpfs defaults,size=512m 0 0 +EOF + +### Set up basic networking stuff +echo "$guest" > etc/hostname +cat > etc/hosts << EOF +127.0.0.1 localhost +$ipaddr $fqdn $guest + +# 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 +ff02::3 ip6-allhosts +EOF +rm -fv etc/udev/rules.d/70-persistent-* +mkdir -p etc/udev/rules.d/ +touch etc/udev/rules.d/75-persistent-net-generator.rules + +cat > etc/network/interfaces << EOF +auto lo +iface lo inet loopback + +allow-hotplug eth0 +iface eth0 inet static + pre-up echo 0 > /proc/sys/net/ipv6/conf/\$IFACE/accept_ra + address $ipaddr/$prefixlen + gateway $gateway + +allow-hotplug eth1 +iface eth1 inet static + address 172.22.130.$hostno/23 +iface eth1 inet6 static + address $ip6addr/64 + gateway $ip6gateway + accept_ra 0 +EOF + +cat > etc/resolv.conf << EOF +nameserver 172.22.130.1 +search $domainname +EOF + +### A couple packages +mv etc/apt/sources.list etc/apt/sources.list.d/debian.list +echo "deb http://security.debian.org/ jessie/updates main" > etc/apt/sources.list.d/security.list +echo "deb $MIRROR jessie-updates main" > etc/apt/sources.list.d/updates.list +chroot . apt-get update +echo "Apt::Install-Recommends 0;" > etc/apt/apt.conf.d/local-recommends +chroot . apt-get install -y locales-all net-tools iproute ifupdown dialog vim netbase udev psmisc usbutils pciutils +chroot . apt-get install -y iputils-ping telnet bind9-host lvm2 +sed -i -e 's/issue_discards = 0/issue_discards = 1/' etc/lvm/lvm.conf + +### Set up kernel and bootloader +chroot . apt-get install -y linux-image-amd64 +DEBIAN_FRONTEND=noninteractive chroot . apt-get install -y grub2 + +! [ -e dev/sda ] +! [ -e dev/sda1 ] +cp -av `readlink -f "$rootdev"` dev/new-root +cp -av `readlink -f "$part1"` dev/new-root1 +chroot . grub-install --modules=part_msdos /dev/new-root +rm -v dev/new-root* + +cp -av `readlink -f "$rootdev"` dev/sda +cp -av `readlink -f "$part1"` dev/sda1 +rm -f boot/grub/device.map +sed -i -e 's/^GRUB_CMDLINE_LINUX=""$/GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"/' etc/default/grub +cat >> etc/default/grub < etc/apt/apt.conf.d/20auto-upgrades << EOF +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Unattended-Upgrade "1"; +EOF + +## trim +mkdir -p etc/cron.daily +tee > etc/cron.daily/local-trim-ext4 << 'EOF' +#!/bin/sh + +# by weasel + +for fs in `awk '$9 == "ext4" && $4 == "/" {print $5}' /proc/self/mountinfo`; do + fstrim "$fs" +done +EOF +chmod +x etc/cron.daily/local-trim-ext4 + +### first boot +cat > first-boot.sh << EOF +#!/bin/bash +set -e +sleep 10 +apt-get install -y acpi-support-base lldpd +apt-get install -y libpam-systemd dbus +apt-get install -y cron +apt-get install -y rsyslog +sed -i -e '/first-boot.sh/d' etc/rc.local +/etc/cron.daily/local-trim-ext4 +rm /first-boot.sh +(sleep 10 ; /sbin/reboot) & +disown %1 +EOF +chmod +x first-boot.sh +sed -i -e '$ i [ -x /first-boot.sh ] && /first-boot.sh' etc/rc.local + + +### clean up +chroot . apt-get clean + +# prepare virsh file +( : #) +cat << EOF + + $guest + $(uuidgen) + 2048 + 2 + + hvm + + + + + + + + + SandyBridge + + + + + + + destroy + restart + restart + + + + + + /usr/bin/kvm + + + + + + + + + + + +EOF +[ "$lvmsize" = "" ] || cat << EOF + + + + + +EOF +cat << EOF + + + + + + + + + + + + + + + + + + + + + + + + +EOF +) > "$diskfileprefix/$guest.xml" + +# and done +trap - EXIT +do_cleanup + +echo "$guest's root password is $rootpw" +echo "SSH host key fingerprints are:" +echo "$sshkeys" +echo "IP addresses:" +echo " $ipaddr" +echo " $ip6addr" +echo +echo "Maybe run" +echo " echo '$hostno' '$ipaddr' '$fqdn' >> '$hostlistfile'" +echo " virsh define '$diskfileprefix/$guest.xml' && rm '$diskfileprefix/$guest.xml'" +echo " virsh autostart '$guest'" +echo " virsh start '$guest'" +echo " virsh console '$guest'" +echo +echo ' for i in `/usr/local/sbin/vm_du_ suggest`; do ln -vsf /usr/local/sbin/vm_du_ /etc/munin/plugins/vm_du_$i; done' +echo ' service munin-node restart; sleep 3; service munin-async restart' -- cgit v1.2.3