Quelle che seguono sono le operazioni che ci hanno consentito di creare l’immagine UML utilizzata dai nostri laboratori Laboratori virtuali netkit
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.
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
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 (?).
Affinchè il boot delle macchine virtuali avvenga correttamente, è necessario procurarsi le script di avvio :
Tali script andranno copiate in /etc/init.d ed inserite nel runlevel opportuno.
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
...
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.
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 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
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