Creazione di una vm UML

Quelle che seguono sono le operazioni che ci hanno consentito di creare l’immagine UML utilizzata dai nostri laboratori Laboratori virtuali netkit

Preparazione del filesystem

Creiamo un file vuoto (in questo caso di 1 Gb)

dd if=/dev/zero of=nuovo_fs count=1 bs=1k seek=$[1*1024*1024]

in cui creare un filesystem (es. reiserfs)

mkfs.reiserfs -f nuovo_fs
...
nuovo_fs is not a block special device
Continue (y/n):y
...

Montiamo (in loop) il filesystem e copiamovi all’interno tutti i file della distribuzione voluta

mount -o loop nuovo_fs /media/uml_fs/
cp -a etch-argo/* /media/uml_fs/

Nota

Per comodità, abbiamo copiato il contenuto di una chroot creata via debian-live.

Modifiche da apportare al sistema copiato

/etc/fstab

Creare un nuovo /etc/fstab con il seguente contenuto

/dev/ubda       /               auto    defaults                1   1
none            /dev/pts        devpts  gid=5,mode=620          0   0
none            /proc           proc    defaults                0   0
tmpfs           /tmp            tmpfs   defaults,size=768M      0   0

/etc/inittab

Modificare /etc/inittab affinchè venga utilizzata /sbin/mingetty al posto di /sbin/getty. E` preferibile commentare le console tty non utilizzate per velocizzare l’avvio della vm

...
1:2345:respawn:/sbin/mingetty --noclear --noissue --autologin root tty0
2:2345:respawn:/sbin/mingetty --noclear --noissue --autologin root tty1
# 3:23:respawn:/sbin/getty 38400 tty3
# 4:23:respawn:/sbin/getty 38400 tty4
# 5:23:respawn:/sbin/getty 38400 tty5
# 6:23:respawn:/sbin/getty 38400 tty6
...

Nota

Avere in /etc/ un file dal nome inittab.orig`, simile ad inittab`, ha portato ad un errore abbastanza serio: netkit leggeva infatti non l’atteso inittab bensì inittab.orig. Il perchè resta al momento un mistero... Probabilmente il discorso vale anche per altri file di configurazione (?).

runlevel

Affinchè il boot delle macchine virtuali avvenga correttamente, è necessario procurarsi le script di avvio :

  • netkit-phase1
  • netkit-phase2
  • netkit-test-phase (al momento non utilizzato)

Tali script andranno copiate in /etc/init.d ed inserite nel runlevel opportuno.

Per Argo-etch (debian based)

Utilizzando /etc/runlevel.conf, sarà necessario aggiungere al file

...
08    0,1,6   S               /etc/init.d/netkit-phase1
99    0,1,6   2,3,4,5         /etc/init.d/netkit-phase2
...

Per argo-lenny (debian based)

A differenza di quanto avveniva su debian Etch, a partire da Debian Lenny, l’utilizzo di /etc/runlevel.conf è cessato. Si dovranno quindi creare i link simbolici alla veccha maniera

cd /etc
rm rcS.d/*firewall
ln -s ../init.d/netkit-phase2   rc2.d/S99netkit-phase2
ln -s ../init.d/netkit-phase1   rcS.d/S37netkit-phase1
ln -s ../init.d/firewall rcS.d/S38firewall

Nota

Posizionare troppo presto l’esecuzione della script di runlevel netkit-phase1 in /etc/rcS.d può portare problemi. Quello che segue è l’ordine che abbiamo ritenuto “ideale”

S01glibc.sh->../init.d/glibc.sh
S02hostname.sh->../init.d/hostname.sh
S02mountkernfs.sh->../init.d/mountkernfs.sh
S03udev->../init.d/udev
S04mountdevsubfs.sh->../init.d/mountdevsubfs.sh
S05bootlogd->../init.d/bootlogd
S05keymap.sh->../init.d/keymap.sh
S07hdparm->../init.d/hdparm
S08hwclockfirst.sh->../init.d/hwclockfirst.sh
S10checkroot.sh->../init.d/checkroot.sh
S11hwclock.sh->../init.d/hwclock.sh
S12mtab.sh->../init.d/mtab.sh
S18ifupdown-clean->../init.d/ifupdown-clean
S20module-init-tools->../init.d/module-init-tools
S30checkfs.sh->../init.d/checkfs.sh
S30procps->../init.d/procps
S35mountall.sh->../init.d/mountall.sh
S36mountall-bootclean.sh->../init.d/mountall-bootclean.sh
S36udev-mtab->../init.d/udev-mtab
S37mountoverflowtmp->../init.d/mountoverflowtmp
S37netkit-phase1->../init.d/netkit-phase1
S38firewall->../init.d/firewall
S39ifupdown->../init.d/ifupdown
S40networking->../init.d/networking
S45mountnfs.sh->../init.d/mountnfs.sh
S46mountnfs-bootclean.sh->../init.d/mountnfs-bootclean.sh
S48console-screen.kbd.sh->../init.d/console-screen.kbd.sh
S55bootmisc.sh->../init.d/bootmisc.sh
S55urandom->../init.d/urandom
S70x11-common->../init.d/x11-common
S75sudo->../init.d/sudo
S99stop-bootlogd-single->../init.d/stop-bootlogd-single

mentre per netkit-phase2, in /etc/rc2.d

S10rsyslog->../init.d/rsyslog
S16ssh->../init.d/ssh
S20uml-utilities->../init.d/uml-utilities
S89cron->../init.d/cron
S99netkit-phase2->../init.d/netkit-phase2
S99rc.local->../init.d/rc.local
S99rmnologin->../init.d/rmnologin
S99stop-bootlogd->../init.d/stop-bootlogd

Nota

Per rendere l’avvio della vm piu veloce abilitiamo solo i servizi necessari. (nell’esempio sopra, molti servizi non sono ancora stati disattivati).

A modifiche ultimate, possiamo smontare il filesystem e testarlo con un kernel uml.

Preparazione del kernel UML

Configurazione

Con kernel recenti non serve nessuna patch ma sono necessari i sorgenti completi.

make menuconfig ARCH=um

Per un corretto e buon funzionamento del kernel UML e’ necessario abilitare le seguenti opzioni

#
# Driver per accedere ai file del pc host come se fosse un filesystem
#
CONFIG_BLK_DEV_UBD=y
CONFIG_BLK_DEV_UBD_SYNC=y
#
# UML Network Devices
#
CONFIG_UML_NET=y
CONFIG_UML_NET_ETHERTAP=y
CONFIG_UML_NET_TUNTAP=y
CONFIG_UML_NET_SLIP=y
CONFIG_UML_NET_DAEMON=y
CONFIG_UML_NET_MCAST=y
# CONFIG_UML_NET_PCAP is not set
CONFIG_UML_NET_SLIRP=y
#
# Connettori virtuali per le connessione delle console e delle porte seriali
#
CONFIG_STDERR_CONSOLE=y
CONFIG_STDIO_CONSOLE=y
CONFIG_SSL=y
CONFIG_NULL_CHAN=y
CONFIG_PORT_CHAN=y
CONFIG_PTY_CHAN=y
CONFIG_TTY_CHAN=y
CONFIG_XTERM_CHAN=y
# CONFIG_NOCONFIG_CHAN is not set
CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
CONFIG_CON_CHAN="xterm"
CONFIG_SSL_CHAN="pty"
#
# Per la condivisione di una parte di filesystem della macchina host
# con la vm UML (opzione utilizzata da Netkit)
#
CONFIG_HOSTFS=y

È consigliabile rimuovere tutti i moduli e le opzioni non utilizzabili da una macchina virtuale (es: supporto al bluetooth ...). Così facendo si otterrà un kernel più snello.

Compilazione

Compilazione del kernel UML e installazione dei moduli nell’apposito filesystem (quello precedentemente montato in loop)

make mrproper
make mrproper ARCH=um
make all ARCH=um
make modules_install ARCH=um INSTALL_MOD_PATH=/media/uml_fs/
strip linux

Il kernel compilato e’ ora pronto per essere testato

./linux-argo-uml ubd0=cow,nuovo_fs

Nota

Se non si lancia questo comando direttamente dalla macchina host con X attivo, utilizzare l’opzione -X all’inizio delle connessione ssh in modo tale da inoltrare nel tunnel ssh l xterm che verra’ generato dalla vm. Se per necessità si volesse utilizzare direttamete la console cambiare il file inittab con

1:2345:respawn:/sbin/getty 38400 console

Generazione di un immagine automatizzata

Per generare generare una immagine.img della nostra macchina virtuale si potrà utilizzare la script seguente

#!/bin/bash
function help () {
cat << FINE
Comando:         `basename $0`
Sintassi:        `basename $0` [ -h ] image_name
Descrizione:     Crea una immagine netkit
Opzioni:         -h      help (Questa pagina di manuale)
                 -d dim  imposta dimensione (def.: 400)
                 -s src  imposta cartella sorgente (chroot)
                 -k ker_dir  copy ker_dir as kernel lib tree
FINE
}
DIM=400
MNT_POINT=/mnt/build
SRC=/usr/src/distro/etch-argo
KERNEL=
while getopts hs:d:k: var
  do
  case $var in
      h) help; exit
          ;;
      d) DIM=$OPTARG
          ;;
      s) SRC=$OPTARG
          ;;
      k) KERNEL=$OPTARG
          ;;
  esac
done
shift ` expr $OPTIND - 1 `
IMAGE=$1
function check () {
    if [ -z "$IMAGE" ] ; then
        help
    fi
}
dd if=/dev/zero of=$IMAGE count=1 bs=1k seek=$[1*1024*$DIM]
# sfdisk -uM  $IMAGE <<EOF
# ,$DIM,L
# EOF
#mkreiserfs -q -f $IMAGE
mkfs -t ext3 $IMAGE
mkdir -p $MNT_POINT
mount -o loop -t ext3 $IMAGE $MNT_POINT || exit 1
cp -a $SRC/* $MNT_POINT
cat <<EOF > $MNT_POINT/etc/fstab
dev/ubda       /               auto    defaults                1   1
none            /dev/pts        devpts  gid=5,mode=620          0   0
none            /proc           proc    defaults                0   0
tmpfs           /tmp            tmpfs   defaults,size=768M      0   0
EOF
# perl -i -pe '{$_ =~ s!([2-6]:23:respawn:/sbin/getty)!\# $1!; }
#    ' $MNT_POINT/etc/inittab
# for file in inittab runlevel.conf
# do
#     cp -av $SRC/etc/$file.uml $MNT_POINT/etc/$file
# done
if [ -n "$KERNEL" ] ; then
    rm -Rf $MNT_POINT/lib/modules
    cp -a $KERNEL/*  $MNT_POINT
fi
umount -d $MNT_POINT

La script necessita di conoscere il path della chroot del nostro sistema ed opzionalmente il path della dir contentente i moduli che intendiamo usare. Ad esempio, per creare l’immagine /tmp/my-image.img a partire dal percorso /path/to/my_chroot utilizzando i moduli in /path/to/my_modules

./crea_netkit_image -s /path/to/my_chroot -k /path/to/my_modules \
-d 1000 /tmp/my-image.img