+#!/bin/sh
+set -e -f ${DRY_RUN:+-n} -u ${TRACE:+-x}
+ # -e: erreur si une commande non testée échoue.
+ # -f: désactive les jokers dans les chemins.
+ # -u: erreur si une variable non-définie est utilisée.
+ # -x: affiche les commandes exécutées sur la sortie d'erreur standard.
+
+tool=${0%/*}
+. "$tool"/env.sh
+
+rule_help () {
+ cat >&2 <<-EOF
+ DESCRIPTION: ce script regroupe des fonctions utilitaires
+ pour gérer la VM des ateliers _depuis_ son hôte ;
+ il sert à la fois d'outil et de documentation.
+ Voir \`$tool/ateliers_hosted' pour les utilitaires côté VM hébergée.
+ SYNTAX: $0 \$RULE \${RULE}_SYNTAX
+ RULES:
+ $(sed -ne 's/^rule_\([^ ]*\) () {\( *#.*\|\)/\t\1\2/p' "$0")
+ ENVIRONMENT:
+ $(sed -ne 's/^readonly \([^ =]*\).*}\( *#.*\|\)$/\t$\1\2/p' "$tool"/env.sh "$0")
+ EOF
+ }
+
+readonly dev_disk="/dev/xvda"
+readonly dev_disk_boot="${dev_disk}1"
+readonly dev_disk_swap="${dev_disk}5"
+readonly dev_disk_root="${dev_disk}6"
+readonly dev_disk_var="${dev_disk}7"
+readonly dev_disk_home="${dev_disk}8"
+
+rule_xen_config_init () {
+ tee /etc/xen/$vm_fqdn.cfg <<-EOF
+ # -*- mode: python; -*-
+ import os, re
+ name = "$vm"
+ arch = os.uname()[4]
+ memory = 2048
+ vcpus = 1
+ vif = ['mac=$vm_mac,bridge=$vm_bridge']
+ disk = ['phy:/dev/domU/$vm_fqdn-disk,hda,w']
+ kernel = "/usr/lib/xen-4.0/boot/hvmloader"
+ builder = 'hvm'
+ device_model = 'qemu-dm'
+ acpi = 1
+ apic = 1
+ # boot on floppy (a), hard disk (c) or CD-ROM (d)
+ #boot = 'd'
+
+ #vnc = 1
+ #sdl = 0
+ #vncconsole = 0
+ #vnclisten = "0.0.0.0"
+ #vncpasswd = ""
+ #usbdevice = 'tablet'
+
+ keymap = 'fr'
+ serial = 'pty'
+ on_poweroff = 'destroy'
+ on_reboot = 'restart'
+ on_crash = 'restart'
+ EOF
+ }
+rule_xen_on () {
+ sudo xm create $vm_fqdn.cfg
+ }
+rule_xen_off () {
+ sudo xm shutdown $vm_fqdn.cfg
+ }
+
+rule_disk_mount () {
+ # Montage du disque de la VM depuis l'hôte
+ test ! -e $vm_dev_disk
+ sudo xm block-attach 0 phy:/dev/domU/$vm_fqdn-disk $vm_dev_disk w
+ }
+rule_disk_unmount () {
+ # Démontage du disque de la VM depuis l'hôte
+ test -e $vm_dev_disk
+ ! mountpoint /mnt/$vm_fqdn
+ sudo xm block-detach 0 $vm_dev_disk
+ }
+rule_disk_part () {
+ # Partitionage du disque de la VM
+ # NOTE: on fait le choix de ne pas utiliser LVM sur la machine virtuelle car :
+ # - pour l'extension de mémoire:
+ # 1. on créera une nouvelle partition sur le LVM de l'hôte
+ # 2. on l'ajoutera comme un disque supplémentaire dans /etc/xen/$vm_fqdn.cfg
+ # 3. on le montera sur /home2 en pensant à changer DHOME=/home2 dans /etc/adduser.conf
+ # - pour la sauvegarde: LVM snapshoot est trop
+ # 1. sauvegarde au niveau applicatif (pgdump, mysqldump)
+ # 2. sauvegarde des configurations (etckeeper, git)
+ # 3. sauvegarde incrémentale et chiffrée des autres fichiers (duplicity)
+ # NOTE:
+ sudo sfdisk -d $vm_dev_disk <<-EOF
+ # partition table of $vm_dev_disk
+ unit: sectors
+
+ ${vm_dev_disk}1 : start= 63, size= 497952, Id=83, bootable
+ ${vm_dev_disk}2 : start= 498015, size=418927005, Id= 5
+ ${vm_dev_disk}3 : start= 0, size= 0, Id= 0
+ ${vm_dev_disk}4 : start= 0, size= 0, Id= 0
+ ${vm_dev_disk}5 : start= 498078, size= 1959867, Id=82
+ ${vm_dev_disk}6 : start= 2458008, size= 29302497, Id=83
+ ${vm_dev_disk}7 : start= 31760568, size= 9767457, Id=83
+ ${vm_dev_disk}8 : start= 41528088, size=377896932, Id=83
+ EOF
+ }
+
+rule_boot_format () {
+ mount | grep -q "^$vm_dev_disk_boot "
+ sudo mkfs.ext2 -m 0 -T small -L "boot" $vm_dev_disk_boot
+ }
+rule_boot_mount () {
+ ! mountpoint /mnt/$vm_fqdn/boot
+ sudo mount -v $vm_dev_disk_boot /mnt/$vm_fqdn/boot
+ }
+rule_boot_unmount () {
+ mountpoint /mnt/$vm_fqdn/boot
+ sudo unmount -v /mnt/$vm_fqdn/boot
+ }
+
+rule_part_clean () {
+ # NOTE: long, optionnel
+ # Déjà fait à la main histoire de pouvoir créer la machine virtuelle plus
+ # rapidement le jour venu.
+ part=$1
+ eval "sudo dd if=/dev/urandom of=\$vm_dev_disk_$part"
+ }
+rule_part_clean_stat () {
+ # USE: exécuter cette fonction dans un shell distinct de rule_part_clean()
+ # lui fait afficher sa progression.
+ part=$1
+ eval "pkill -USR1 -f \"^dd if=/dev/urandom of=\$vm_dev_disk_$part\""
+ }
+rule_part_format_root () {
+ # DECRIPTION: Formatage de /
+ part="root"
+ eval dev="\$vm_dev_disk_$part"
+ sudo cryptsetup luksFormat --hash=sha512 --key-size=512 --key-file=- \
+ --cipher=aes-xts-essiv:sha256 --align-payload=8 $dev
+ sudo cryptsetup luksOpen --key-file=- $dev ${vm}_${part}_deciphered
+ sudo mkfs.ext4 -m 5 -T ext4 -L ${vm}_$part -E stripe_width=32,resize=15G \
+ /dev/mapper/${vm}_${part}_deciphered
+ }
+rule_format_part () {
+ # DESCRIPTION: formatage d'une partition distincte de /
+ # NOTE: la clef de chiffrement est dérivée de celle de /,
+ # / doit être déchiffrée pour que cela fonctionne.
+ part=$1
+ eval dev="\$vm_dev_disk_$part"
+ test -e /dev/mapper/${vm}_root_deciphered
+ sudo /lib/cryptsetup/scripts/decrypt_derived ${vm}_root_deciphered |
+ sudo cryptsetup luksFormat --key-file=- --hash=sha512 --key-size=512 --cipher=aes-xts-essiv:sha256 $dev
+ }
+rule_mount_part () {
+ part=$1
+ eval dev="\$vm_dev_disk_$part"
+ test -e /dev/mapper/${vm}_root_deciphered
+ sudo /lib/cryptsetup/scripts/decrypt_derived ${vm}_root_deciphered |
+ sudo cryptsetup luksOpen --key-file=- $dev ${vm}_${part}_deciphered
+ }
+rule_unmount_part () {
+ part=$1
+ eval dev="\$vm_dev_disk_$part"
+ sudo cryptsetup luksClose ${vm}_${part}_deciphered
+ }
+rule_part_format_swap () {
+ part="swap"
+ rule_format_part $part
+ rule_mount_part $part
+ sudo mkswap -f -L ${vm}_swap /dev/mapper/${vm}_${part}_deciphered
+ rule_unmount_part $part
+ }
+rule_part_format_var () {
+ part="var"
+ rule_format_part $part
+ rule_mount_part $part
+ sudo mkfs.ext4 -m 5 -T ext4 -L ${vm}_$part -E stripe_width=32,resize=5G /dev/mapper/${vm}_${part}_deciphered
+ rule_unmount_part $part
+ }
+rule_part_format_home () {
+ part="home"
+ rule_format_part $part
+ rule_mount_part $part
+ sudo mkfs.ext4 -m 5 -T ext4 -L ${vm}_$part -E stripe_width=32,resize=200G /dev/mapper/${vm}_${part}_deciphered
+ rule_unmount_part $part
+ }
+
+rule_install_debian () {
+ sudo DEBOOTSTRAP_DIR=/usr/share/debootstrap/ debootstrap \
+ --arch=$vm_arch --verbose --keyring=/usr/share/keyrings/debian-archive-keyring.gpg \
+ --exclude=vim-tiny \
+ --include=$(printf '%s,' \
+ acl \
+ bsdmainutils \
+ busybox \
+ ca-certificates \
+ console-setup \
+ cryptsetup \
+ dash \
+ dnsutils \
+ dropbear \
+ etckeeper \
+ hashalot \
+ htop \
+ ifupdown \
+ initramfs-tools \
+ kbd \
+ less \
+ ncurses-term \
+ openssh-client \
+ openssh-server \
+ openssl \
+ pciutils \
+ procps \
+ quota \
+ quotatool \
+ rsync \
+ screen \
+ sudo \
+ sysprofile \
+ vim-nox \
+ wget \
+ zsh \
+ ) \
+ $vm_lsb_name /mnt/$vm_fqdn/ http://ftp.fr.debian.org/debian/
+ }
+rule_chroot () {
+ mountpoint /mnt/$vm_fqdn
+ mountpoint /mnt/$vm_fqdn/boot
+ mount --bind /dev /mnt/$vm_fqdn/dev
+ sudo chroot /mnt/$vm_fqdn /bin/bash
+ umount /mnt/$vm_fqdn/dev
+ }
+
+rule=${1:-help}
+${1+shift}
+rule_$rule "$@"