#!/bin/bash
# Script managed by Ansible, do not edit
#
#    Copyright (C) 2017  Free Software Foundation
#    Copyright (C) 2017  Ruben Rodriguez <ruben@fsf.org>
#
#    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 3 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 should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#
# https://dsa.debian.org/howto/install-kvm/
# dependencies
# apt install --no-install-recommends libvirt-dev kvm virtinst xfsprogs pwgen

set -e
export LANG=C
export LC_ALL=C

if [ $# -lt 4 ]; then
  echo "Usage: $0 hostname.foo.bar disksize(MB) ramsize(MB) cpucount [distro_release_codename]"
  echo "Example: $0 www.gnu.org 5000 512 2 flidas"
  echo "supported codenames are flidas, belenos and stretch"
  exit 1
fi

HOST=$1
HOSTSHORT=$(echo $HOST | sed 's/\..*//')
POOL=rbd

if ! getent hosts $HOST > /dev/null; then
  echo "Could not resolve the hostname to an IP. Add it to the DNS first!"
  exit 1
fi

IP=$(getent ahosts $HOST |grep ^209.*RAW| sed 's/ .*//')
IP6=$(getent ahosts $HOST |grep ^2001.*RAW| sed 's/ .*//')
NIC=eth0
GATEWAY=209.51.188.1
GATEWAY6=2001:470:142::1

SIZE=$2
RAM=$3
CPUS=$4

RELEASE=flidas
[ 1${5}1 != 11 ] && RELEASE=$5
case $RELEASE in
  flidas|belenos)
    archive=http://us.archive.trisquel.info/trisquel
    linux_pkg=linux-image-virtual
    ;;
  stretch)
    archive=http://deb.debian.org/debian/
    linux_pkg=linux-image-amd64
    ;;
  *)
    echo "$0: error: unknown release"
    exit 1
    ;;
esac

rbd create $HOST --size $SIZE -p $POOL --image-format=2 --image-feature exclusive-lock,object-map,fast-diff,layering
DEVICE=$(rbd-nbd map $HOST)

TARGET=$(mktemp -d)
KEYFILE=/dev/shm/keyfile
pwgen 128 -s -1 | xargs echo -n > $KEYFILE
echo YES | cryptsetup luksFormat -y --cipher aes-xts-plain64 --hash sha256 --use-urandom --key-size 256  $DEVICE --key-file=$KEYFILE
cryptsetup luksOpen $DEVICE $HOST-crypt0 --key-file=$KEYFILE
mkfs.xfs -i size=2048 -s size=4096 -d agcount=4 /dev/mapper/$HOST-crypt0
mount /dev/mapper/$HOST-crypt0 $TARGET -o discard,noatime,nodiratime

if ! [ -d /srv/debootstrap-cache/${RELEASE} ] ; then
  mkdir -p /srv/debootstrap-cache/${RELEASE}
  eatmydata debootstrap --exclude=resolvconf ${RELEASE} /srv/debootstrap-cache/${RELEASE} $archive
fi
eatmydata cp -a /srv/debootstrap-cache/${RELEASE}/* $TARGET

mknod $TARGET/dev/sda b 8 0
mkdir $TARGET/dev/mapper
cp -av $(readlink -f /dev/mapper/${HOST}-crypt0) $TARGET/dev/mapper/${HOST}-crypt0
cat << EOF > $TARGET/boot/keyscript.sh
#!/bin/sh
echo -n $(cat $KEYFILE)
EOF
chmod 700 $TARGET/boot/keyscript.sh $TARGET/boot/

cat << EOF > /dev/shm/grub.cfg
cryptomount -k /keyfile hd0
linux (crypto0)/vmlinuz root=/dev/mapper/${HOST}-crypt0 ro elevator=noop console=tty0 console=ttyS0,115200 biosdevname=0 net.ifnames=0
initrd (crypto0)/initrd.img
boot
EOF
dd if=/dev/zero of=/dev/shm/memdisk bs=1M count=1
mkfs.ext2 /dev/shm/memdisk
mkdir /dev/shm/memdiskmount || true
mount /dev/shm/memdisk /dev/shm/memdiskmount
cp $KEYFILE /dev/shm/memdiskmount/
umount /dev/shm/memdiskmount
grub-mkimage -v -C xz -c /dev/shm/grub.cfg  -O i386-pc  -o /var/lib/libvirt/images/grub-$HOST.bin  biosdisk ext2 linux xfs normal luks help crypto cryptodisk zfscrypt gcry_sha512 gcry_sha256 echo cat memdisk -m /dev/shm/memdisk

cat << EOF > $TARGET/etc/fstab
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/mapper/${HOST}-crypt0 / xfs noatime,nodiratime,sunit=8192,swidth=8192 0 1
EOF

echo "${HOST}-crypt0 /dev/sda none luks,discard,keyscript=/boot/keyscript.sh" > $TARGET/etc/crypttab

mount -t proc none $TARGET/proc
mount -o bind /dev $TARGET/dev

case $RELEASE in
  flidas|belenos)
    cat << EOF > $TARGET/etc/apt/sources.list
deb http://us.archive.trisquel.info/trisquel/ ${RELEASE} main
deb http://us.archive.trisquel.info/trisquel/ ${RELEASE}-updates main
deb http://archive.trisquel.info/trisquel ${RELEASE}-security main
EOF
    ;;
  stretch)
    cat << EOF > $TARGET/etc/apt/sources.list
deb http://http.us.debian.org/debian ${RELEASE} main
deb http://security.debian.org/ ${RELEASE}/updates main
deb http://http.us.debian.org/debian ${RELEASE}-updates main
EOF
    ;;
esac

echo "nameserver 209.51.188.16" > $TARGET/etc/resolv.conf

# For disabling upstart during initial setup
cat << EOF > $TARGET/usr/sbin/policy-rc.d
#!/bin/sh
exit 101
EOF
chmod 755 $TARGET/usr/sbin/policy-rc.d

cp /usr/lib/x86_64-linux-gnu/libeatmydata.so $TARGET/usr/lib/x86_64-linux-gnu/libeatmydata.so
DEBIAN_FRONTEND=noninteractive eatmydata chroot $TARGET apt-get update
# busybox-static needed for debian stretch
DEBIAN_FRONTEND=noninteractive eatmydata chroot $TARGET apt-get dist-upgrade --force-yes -y -o Dpkg::Options::="--force-confnew"
DEBIAN_FRONTEND=noninteractive eatmydata chroot $TARGET apt-get install --force-yes -y --no-install-recommends $linux_pkg ssh acpid busybox-static xfsprogs cryptsetup python3-apt python

rm $TARGET/usr/sbin/policy-rc.d

# Set root password
ROOTPW=$(pwgen 12 -s -1)
echo root:$ROOTPW | chroot $TARGET chpasswd

cat << EOF > $TARGET/etc/init/ttykvm.conf
# ttykvm - getty
#
# This service maintains a getty on tty1 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345]

stop on runlevel [!2345]

respawn
exec /sbin/getty -8 115200 ttyS0 xterm
EOF

cat << EOF > $TARGET/etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto $NIC
iface $NIC inet static
  address $IP
  gateway $GATEWAY
  netmask 255.255.255.0
  hostname $HOST

iface eth0 inet6 static
  pre-up echo 0 > /proc/sys/net/ipv6/conf/eth0/accept_dad
  address $IP6
  netmask 48
  gateway $GATEWAY6
  hostname $HOST
EOF

cat << EOF  > $TARGET/etc/resolv.conf
domain fsf.org
search fsf.org
nameserver 209.51.188.16
EOF

echo $HOST > $TARGET/etc/hostname

cat << EOF  > $TARGET/etc/hosts
127.0.0.1       localhost
$IP    $HOST $HOSTSHORT

::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

mkdir $TARGET/root/.ssh
echo 'from="74.94.156.210" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIImP7xYaUTag4/cNyy8W//T4SZyD3bFtjSac3U7t41bh Ansible' > $TARGET/root/.ssh/authorized_keys

rm $TARGET/usr/lib/x86_64-linux-gnu/libeatmydata.so
umount $TARGET/proc
umount $TARGET/dev
umount $TARGET
cryptsetup luksClose /dev/mapper/${HOST}-crypt0
rbd-nbd unmap $DEVICE

cat << EOF > /tmp/disk.xml
    <disk type='network' device='disk'>
      <driver name='qemu' cache='writeback' discard='unmap' type='raw'  />
      <auth username='libvirt'>
        <secret type='ceph' uuid='dc8e8240-15b4-47ae-896b-6632aec8103e'/>
      </auth>
      <source protocol='rbd' name='$POOL/$HOST'>
        <host name='cephmon1' port='6789'/>
        <host name='cephmon2' port='6789'/>
        <host name='cephmon3' port='6789'/>
      </source>
      <target dev='sda' bus='scsi'/>
    </disk>
EOF

virt-install --name $HOST  --graphics vnc --boot kernel=/var/lib/libvirt/images/grub-$HOST.bin  --network type=direct,source=macvtap-bond0,source_mode=bridge,model=virtio --disk none --noautoconsole --controller scsi,model=virtio-scsi --cpu host --vcpus=${CPUS} --memory=$RAM,hugepages=true --cpuset=auto
virsh attach-device $HOST /tmp/disk.xml --persistent
virsh dumpxml $HOST > /tmp/tmp.xml
#sed "1s#># xmlns:qemu=\'http://libvirt.org/schemas/domain/qemu/1.0'>#; s#</domain>#<qemu:commandline><qemu:arg value='-set'/><qemu:arg value='device.scsi0-0-0-0.min_io_size=4194304'/><qemu:arg value='-set'/><qemu:arg value='device.scsi0-0-0-0.opt_io_size=4194304'/></qemu:commandline></domain>#" /tmp/tmp.xml -i
sed "/virtio-scsi/a <driver queues='$CPUS'/>" /tmp/tmp.xml -i
virsh destroy $HOST
# This allows ipv6 to do neighbour discovery https://superuser.com/questions/944678/how-to-configure-macvtap-to-let-it-pass-multicast-packet-correctly
#sed "s_<interface type='direct.*_<interface type='direct' trustGuestRxFilters='yes'>_" -i /tmp/tmp.xml
virsh create /tmp/tmp.xml

echo "

Created new virtual machine $HOST

ROOT PASSWORD	: $ROOTPW
LUKS KEY	: `cat $KEYFILE`
IP		: $IP
RBD IMAGE	: $POOL/$HOST
SIZE		: $SIZE
RAM SIZE	: $RAM
"

rm /tmp/tmp.xml
rm -f $KEYFILE
rm -rf /dev/shm/memdisk* /dev/shm/grub.cfg

exit 0
