|
#!/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
|