Project

General

Profile

FSFVM ยป create-vm-ceph-luks.sh

Denis 'GNUtoo' Carikli, 02/24/2020 08:15 PM

 
#!/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
    (1-1/1)