Tags

arm bin_sh blocage blosxom bsd bsdfrance cblog certification chroot cluster dg834 dhcp dns dnsmasq domU dovecot fail-over fail2ban firefox freebsd ftp git guruplug install ipv6 jail kernel kimsufi lex libre linutop makefile ml150 mohawk netbook netbsd nginx ntp ntp.org openbsd openntpd openrd openwrt orke pkgng poudriere proxy python rescue reverse rmll route rrdcgi sendmail sieve sl2009 ssd symon update usb var_empty vimperator world xen yacc zfs

Powered by

blOg
maRkdown
awK
shEll

30/12/2012

[ freebsd xen domU rescue ]

201212301200 freebsd xen domU rescue

Un domU à la sauce FreeBSD

J'ai à ma disposition un ordinateur portable Dell Latitude D810 généreusement doté de 2 Go de ram, d'un disque accueuillant de 40 Go, le tout propulsé par un unique mais véloce Pentium Mobile se déplaçant à la vitesse supersonique de 1.73 GHz. Tout ça à la portée du premier quidam venu c'est fou, non ?

Devant cette débauche de puissance, on ne peut que s'incliner. Et installer un NetBSD 6.0 i386 parce que les serviettes oranges ça roxe. Quelles sont les origines de cette roxitude ? Une déscendance directe avec Unix (le vrai, le seul et l'unique, sorti des entrailles d'un PDP 11 il y a plus de 40 ans) ? 20 ans d'histoire (sans compter sa longue gestion au sein du CSRG, hébergé par l'University of Berkeley, California) ? Une accointance particulière avec le projet Xen ? Son récent support de LVM ? Une communauté française particulièrement impliquée (de par ses contributions de qualité et de ses rassemblements de haut niveau) ?

Nul doute que nous sommes en présence d'un OS du bien. Il est aisé de trouver moultes documentations relatives à son installation (dans le cas contraire n'hésitez pas à vous procurer le Gnu Linux Magazine France n°115) et l'ajout de Xen (version 4.1) est trivial. Mais un OS du bien c'est bien, deux c'est mieux. Je me propose donc de détailler les différentes étapes menant à l'obtention d'un domU FreeBSD 9.0.

Les caractéristiques de la machine et une volonté de parcourir des chemins peu fréquentés expliquent les choix suivants:

Le projet FreeBSD ne proposant pas de kernel xenifié tout prêt, il va falloir passer par les sources. Une machine (même virtuelle) avec un FreeBSD i386 (le kernel compilé depuis une machine X86_64 n'était pas reconnu comme PAE, pré-requis indispensable à l'utilisation de Xen 4.1), la bible sous les yeux, les sources en version 9.0 fraichement récupérés et nous voilà prêt à compiler 2 kernels:

Point de compilation sans configuration et un peu de lecture. Inutile de compiler l'ensemble des modules, les divers périphériques disponibles dans un domU sont tous identifiés et intégrés dans le kernel. Seul bémol: la présence des options de debug. On peut, sans être trop téméraire, s'en passer aisément (tout comme de nfs dont je ne suis pas un fervent adepte):

# cat /usr/src/sys/i386/conf/XEN_PROD
include XEN

ident           XEN_PROD

makeoptions     DEBUG=
makeoptions     MODULES_OVERRIDE=

nooptions       SCTP                    # Stream Control Transmission Protocol
nooptions       NFSCL                   # New Network Filesystem Client
nooptions       NFSD                    # New Network Filesystem Server
nooptions       NFSLOCKD                # Network Lock Manager
nooptions       NFS_ROOT                # NFS usable as /, requires NFSCL

# Debugging for use in -current
nooptions       KDB                     # Enable kernel debugger support.
nooptions       DDB                     # Support DDB.
nooptions       GDB                     # Support remote GDB.
nooptions       DEADLKRES               # Enable the deadlock resolver
nooptions       INVARIANTS              # Enable calls of extra sanity checking
nooptions       INVARIANT_SUPPORT       # Extra sanity checks of internal structures, required by INVARIANTS
nooptions       WITNESS                 # Enable checks to detect deadlocks and cycles
nooptions       WITNESS_SKIPSPIN        # Don't run witness on spinlocks for speed
# cd /usr/src
# make buildkernel KERNCONF=XEN_PROD
# ls -l /usr/obj/usr/src/sys/XEN_PROD/kernel
-rwxr-xr-x  1 root  wheel  3962117 Dec 28 17:27 /usr/obj/usr/src/sys/XEN_PROD/kernel

J'ai dit mollo sur l'espace disque. Je n'utiliserais donc pas les supports habituels (oui môssieur, même les 130 Mo du bootonly sont encore trop pour moi :)

FreeBSD-9.0-RELEASE-i386-bootonly.iso    131 582 KB
FreeBSD-9.0-RELEASE-i386-disc1.iso       513 882 KB
FreeBSD-9.0-RELEASE-i386-dvd1.iso      2 191 632 KB
FreeBSD-9.0-RELEASE-i386-memstick.img    547 752 KB

Pour comprendre la suite des évènements, passons en revue les étapes de l'installation d'un OS du bien:

  1. boot du kernel
  2. obtention d'un shell
  3. préparation du support de destination
  4. installation du système
  5. configuration

Les étapes 2 à 5 sont souvent dévolues à un programme d'installation (le vénérable sysinstall ou le récent bsdinstall). Afin de mimer OpenBSD ou NetBSD, je souhaite construire un kernel contenant de quoi installer ma boule de geisha. Ce kernel contiendra un ramdisk, idéalement peuplé du programme d'installation. Mais là où le bât blesse, c'est que la page de manuel de sysinstall est claire:

 This product is currently at the end of its life cycle and will eventually be replaced.

bsdinstall est quant à lui un script shell faisant appel à d'autres scripts ou programmes:

# ls -l /usr/libexec/bsdinstall/
total 200
-r-xr-xr-x  1 root  wheel   1570 Jan  3  2012 adduser
-r-xr-xr-x  1 root  wheel   7356 Jan  3  2012 auto
-r-xr-xr-x  2 root  wheel  39888 Jan  3  2012 autopart
-r-xr-xr-x  1 root  wheel   2591 Jan  3  2012 checksum
-r-xr-xr-x  1 root  wheel   1680 Jan  3  2012 config
-r-xr-xr-x  1 root  wheel   8436 Jan  3  2012 distextract
-r-xr-xr-x  1 root  wheel   8452 Jan  3  2012 distfetch
-r-xr-xr-x  1 root  wheel   3446 Jan  3  2012 docsinstall
-r-xr-xr-x  1 root  wheel   2053 Jan  3  2012 hostname
-r-xr-xr-x  1 root  wheel   3851 Jan  3  2012 jail
-r-xr-xr-x  1 root  wheel   1747 Jan  3  2012 keymap
-r-xr-xr-x  1 root  wheel   8663 Jan  3  2012 mirrorselect
-r-xr-xr-x  1 root  wheel   2225 Jan  3  2012 mount
-r-xr-xr-x  1 root  wheel   6253 Jan  3  2012 netconfig
-r-xr-xr-x  1 root  wheel   3496 Jan  3  2012 netconfig_ipv4
-r-xr-xr-x  1 root  wheel   4543 Jan  3  2012 netconfig_ipv6
-r-xr-xr-x  2 root  wheel  39888 Jan  3  2012 partedit
-r-xr-xr-x  1 root  wheel   1635 Jan  3  2012 rootpass
-r-xr-xr-x  1 root  wheel   2895 Jan  3  2012 services
-r-xr-xr-x  1 root  wheel   1477 Jan  3  2012 time
-r-xr-xr-x  1 root  wheel   1810 Jan  3  2012 umount
-r-xr-xr-x  1 root  wheel   4700 Jan  3  2012 wlanconfig

Il serait assez laborieux de faire la liste de tous les binaires (et de leurs dépendances respectives) utilisés, car même s'ils sont tous compris dans "base", je ne vais pas faire rentrer la moitié de "base" dans un kernel.

Mes précédentes aventures m'ont fait découvrir le "rescue" et j'ai décidé d'approfondir cette piste. Un rapide coup d'oeil à "/rescue" nous apprend 2 choses:

Les plus perspicaces auront remarqué l'absence de fetch, ftp ou nc. Aucun outil pour récupérer un fichier (au hasard base.txz). Casse la tienne comme dit si bien mon ami Béru, on va phalanger ça.

Après lecture de librescue/Makefile et rescue/Makefile, je configure la compilation de "rescue" de la sorte:

# cat /root/etc/src_xen_install.conf
WITHOUT_RCMDS="yes"
WITHOUT_TCSH="yes"
WITHOUT_ATM="yes"
#WITHOUT_INET6_SUPPORT="yes"
WITHOUT_IPFILTER="yes"
WITHOUT_IPX="yes"
WITHOUT_ZFS="yes"
WITHOUT_NIS="yes"
WITHOUT_HESIOD="yes"
#WITHOUT_OPENSSL="yes"

Au résultat:

# cd /usr/src/rescue/
# make SRCCONF=/root/etc/src_xen_install.conf obj
# make SRCCONF=/root/etc/src_xen_install.conf
# ls -l /usr/obj/usr/src/rescue/rescue/rescue
-rwxr-xr-x  1 root  wheel  3778132 Dec 29 08:53 /usr/obj/usr/src/rescue/rescue/rescue

Pour rajouter un binaire à notre "rescue", il faut malheureusement éditer rescue/Makefile. Inutile de sortir la tronçonneuse pour alléger la partie CRUNCH_PROGS_bin=, le gain ne serait que de quelques centaines de Ko. Si certains esprits chafouins avaient l'idée saugrenue d'objecter que fetch serait plus approprié, je leur souhaite bon courage avec la lib ssl.

# diff -u rescue/Makefile.orig rescue/Makefile
--- rescue/Makefile.orig        2012-12-29 09:01:22.000000000 +0100
+++ rescue/Makefile     2012-12-29 12:50:24.000000000 +0100
@@ -206,6 +206,7 @@
 CRUNCH_PROGS_usr.bin+= id
 CRUNCH_ALIAS_id= groups whoami
 
+CRUNCH_PROGS_usr.bin+= ftp
 ##################################################################
 # Programs from stock /usr/sbin
 #

Au résultat:

# ls -l /usr/obj/usr/src/rescue/rescue/rescue
-rwxr-xr-x  1 root  wheel  3897468 Dec 29 12:52 /usr/obj/usr/src/rescue/rescue/rescue

Le "rescue" est prêt, reste à l'intégrer à notre kernel:

# dd if=/dev/zero of=/tmp/mfs_image bs=1M count=5
5+0 records in
5+0 records out
5242880 bytes transferred in 0.017344 secs (302287859 bytes/sec)
# mdconfig -a -t vnode -f /tmp/mfs_image -u 0
# gpart create -s gpt md0
md0 created
# gpart add -t freebsd-ufs md0
md0p1 added
# newfs -O1 -o space -m 0 md0p1
/dev/md0p1: 5.0MB (10168 sectors) block size 32768, fragment size 4096
        using 2 cylinder groups of 4.00MB, 128 blks, 256 inodes.
super-block backups (for fsck -b #) at:
 64, 8256
# mount /dev/md0p1 /mnt
# mkdir /mnt/{rescue,dev,disk}
# cd /usr/src/rescue/
# make SRCCONF=/root/etc/src_xen_install.conf DESTDIR=/mnt DONTSTRIP=1 install
# cat /usr/src/sys/i386/conf/XEN_INSTALL 
include XEN_PROD

ident           XEN_INSTALL

options         MD_ROOT                 # MD is a potential root device
options         MD_ROOT_SIZE=5120 # 5M
makeoptions     MFS_IMAGE=/tmp/mfs_image
options         ROOTDEVNAME=\"ufs:/dev/md0p1\"
# umount /mnt
# mdconfig -d -u 0
# cd /usr/src
# make buildkernel KERNCONF=XEN_INSTALL
[ snip des trucs ]
>>> Kernel build for XEN_INSTALL completed on Sat Dec 29 13:40:32 CET 2012
--------------------------------------------------------------
# ls -l /usr/obj/usr/src/sys/XEN_INSTALL/kernel
-rwxr-xr-x  1 root  wheel  9205179 Dec 29 13:40 /usr/obj/usr/src/sys/XEN_INSTALL/kernel

Il est temps d'immortaliser tout ce travail:

$ md5 freebsd*
MD5 (freebsd-INSTALL_XEN_DOMU) = e763357ad52622ba5f5b2dcba9c5d373
MD5 (freebsd_XEN_DOMU) = 77d01b45d09e23a05962119f07765505
$ sha256  freebsd*
SHA256 (freebsd-INSTALL_XEN_DOMU) = 9a2f935cbc6acebdd1a165d9b390822a303ad6db41db7c11ae5862e8e78ff9dd
SHA256 (freebsd_XEN_DOMU) = d4fd2a4061ebe507e760ec4241354dbfaeafd97457faa17eba1b57b874e7e024

Une fois tout ce beau monde copié sur notre dom0, on peut passer à la configuration du domU freebsd. Je rappelle que LVM est désormais disponible sur nos serviettes oranges, autant en profiter (vg00 est mon volume group principal):

# lvm lvcreate --size 10G -n lv_freebsd vg00
  Logical volume "lv_freebsd" created
# lvm lvdisplay /dev/vg00/lv_freebsd
  --- Logical volume ---
  LV Name                /dev/vg00/lv_freebsd
  VG Name                vg00
  LV UUID                E2ReS2-e9mh-D1KB-EHXg-PcKz-QYbt-rRLIw6
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                10.00 GiB
  Current LE             2560
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     0
  Block device           169:2

La configuration du domU pour l'installation:

# cat /root/etc/freebsd.cfg 
kernel      = '/root/xen/freebsd-INSTALL_XEN_DOMU'
memory      = '256'
disk        = [ 'phy:/dev/mapper/vg00-lv_freebsd,hda,w' ]
name        = 'xenfree.bsdsx.fr'
vif         = [ 'mac=00:16:3e:00:00:51,bridge=bridge0', 'mac=00:16:3e:00:01:51,bridge=bridge1' ]
on_poweroff = 'destroy'
on_reboot   = 'restart'
on_crash    = 'restart'
extra       = 'console=hvc0,boot_verbose,kern.hz=100,vfs.root.mountfrom=ufs:/dev/md0p1'
  1. mots concernant le réseau:

J'utilise xen en mode brouteur et pleins d'interfaces, une adaptation à votre propre utilisation est sans doute nécessaire.

Même si tout semble prévu, il n'est pas possible, depuis le rescue, d'utiliser dhclient. Cette possibilité nous aurait permis d'avoir un accès réseau "complet" (passerelle, serveurs de noms ...) et de pouvoir récupérer base.txz depuis les sites officiels. Il faudra donc se contenter de configurer manuellement une interface réseau (xn0) et utiliser des adresses ip en lieu et place de nom d'hôte. Je vais donc servir base.txz en utilisant les outils disponibles sur le dom0 (inetd et /usr/libexec/httpd):

$ grep ^http /etc/inetd.conf 
http            stream  tcp     nowait:600      _httpd  /usr/libexec/httpd      httpd /var/www
$ ls -l /var/www/freebsd/9.0/
total 105792
-rw-r--r--  1 root  wheel  54107736 Dec 17 21:47 base.txz
# pkill -HUP inetd

Dernière recommandation: ne pas tenir compte du message suivant:

[XEN] hypervisor wallclock nudged; nudging TOD.

Il est temps de rentrer dans le vif du sujet:

# xm create /home/dsx/etc/freebsd.cfg -c
Using config file "/home/dsx/etc/freebsd.cfg".
Started domain xenfree.bsdsx.fr (id=23)
                                       WARNING: loader(8) metadata is missing!
Copyright (c) 1992-2012 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 9.0-RELEASE-p5 #5: Sat Dec 29 16:45:44 CET 2012
    dsx@dsxbsd001:/usr/obj/usr/src/sys/XEN_INSTALL i386
Xen reported: 1729.021 MHz processor.
Timecounter "ixen" frequency 1953125 Hz quality 0
CPU: Intel(R) Pentium(R) M processor 1.73GHz (1729.02-MHz 686-class CPU)
  Origin = "GenuineIntel"  Id = 0x6d8  Family = 6  Model = d  Stepping = 8
  Features=0xafe1fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,TM,PBE>
  Features2=0x180<EST,TM2>
  AMD Features=0x100000<NX>
real memory  = 268435456 (256 MB)
avail memory = 251011072 (239 MB)
[XEN] IPI cpu=0 irq=128 vector=RESCHEDULE_VECTOR (0)
[XEN] IPI cpu=0 irq=129 vector=CALL_FUNCTION_VECTOR (1)
[XEN] xen_rtc_probe: probing Hypervisor RTC clock
rtc0: <Xen Hypervisor Clock> on motherboard
[XEN] xen_rtc_attach: attaching Hypervisor RTC clock
xenstore0: <XenStore> on motherboard
xc0: <Xen Console> on motherboard
Event timer "ixen" quality 600
Timecounters tick every 10.000 msec
[XEN] hypervisor wallclock nudged; nudging TOD.
xenbusb_front0: <Xen Frontend Devices> on xenstore0
xn0: <Virtual Network Interface> at device/vif/0 on xenbusb_front0
xn0: Ethernet address: 00:16:3e:00:00:51
xn1: <Virtual Network Interface> at device/vif/1 on xenbusb_front0
xn1: Ethernet address: 00:16:3e:00:01:51
xenbusb_back0: <Xen Backend Devices> on xenstore0
xctrl0: <Xen Control Device> on xenstore0
xbd0: 10240MB <Virtual Block Device> at device/vbd/768 on xenbusb_front0
xbd0: attaching as ad0
xn0: backend features:
xn1: backend features:
Timecounter "TSC" frequency 1729021000 Hz quality 800
Trying to mount root from ufs:/dev/md0p1 []...
rtc0: [XEN] xen_rtc_gettime
rtc0: [XEN] xen_rtc_gettime: wallclock 1355568504 sec; 833095242 nsec
rtc0: [XEN] xen_rtc_gettime: uptime 1291968 sec; 51658017 nsec
rtc0: [XEN] xen_rtc_gettime: TOD 1356860472 sec; 884753259 nsec
Dec 30 09:41:13 init: login_getclass: unknown class 'daemon'
cannot open /etc/rc: No such file or directory
Enter full pathname of shell or RETURN for /rescue/sh: [XEN] hypervisor wallclock nudged; nudging TOD.

Cannot read termcap database;
using dumb terminal settings.

# gpart create -s gpt ad0
ad0 created
# gpart add -t freebsd-swap -s 1G  ad0
ad0p1 added
# gpart add -t freebsd-ufs  ad0
ad0p2 added
# newfs ad0p2
/dev/ad0p2: 9216.0MB (18874296 sectors) block size 32768, fragment size 4096
        using 13 cylinder groups of 740.00MB, 23680 blks, 47360 inodes.
super-block backups (for fsck -b #) at:
 192, 1515712, 3031232, 4546752, 6062272, 7577792, 9093312, 10608832, 12124352,
 13639872, 15155392, 16670912, 18186432
newfs: Cannot retrieve operator gid, using gid 0.
# mount /dev/ad0p2 /disk
# ifconfig xn0 up
xn0: link state changed to DOWN
xn0: link state changed to UP
# ifconfig xn0 inet 10.30.12.51 netmask 255.255.255.0
# ping -c 2 10.30.12.1
PING 10.30.12.1 (10.30.12.1): 56 data bytes
64 bytes from 10.30.12.1: icmp_seq=0 ttl=255 time=0.442 ms
64 bytes from 10.30.12.1: icmp_seq=1 ttl=255 time=0.146 ms

--- 10.30.12.1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.146/0.294/0.442/0.148 ms
# cd /disk
# ftp -4 http://10.30.12.1/freebsd/9.0/base.txz
ftp: Can't lookup `10.30.12.1:http': servname not supported for ai_socktype
# ftp -4 http://10.30.12.1:80/freebsd/9.0/base.txz
Requesting http://10.30.12.1:80/freebsd/9.0/base.txz
54107736 bytes retrieved in 00:04 (11.12 MiB/s)
# md5 base.txz 
MD5 (base.txz) = 38d2dca70b768f6992e1cf11af663f0b
# tar xzpf base.txz
# echo '# Device               Mountpoint      FStype  Options         Dump    Pass#' > /disk/etc/fstab
# echo '/dev/ad0p1             none            swap    sw              0       0' >> /disk/etc/fstab 
# echo '/dev/ad0p2             /               ufs     rw              1       1' >> /disk/etc/fstab
# sed -i '' '/^ttyv/d' /disk/etc/ttys
# echo 'xc0     "/usr/libexec/getty Pc"         vt100   on  secure' >> /disk/etc/ttys

Le premier ftp est juste là pour montrer que sans /etc/services, il faut connaitre les numéros de port par coeur :) Arrivé à ce stade, on peut se caresser le pubis. Le plus dur est fait, il nous reste l'étape 5 (configuration). On peut:

Je préfère personnellement la dernière solution, même si elle implique un reboot supplémentaire.

Le fichier de configuration final:

#kernel      = '/home/dsx/xen/freebsd-INSTALL_XEN_DOMU'
kernel      = '/home/dsx/xen/freebsd_XEN_DOMU'
memory      = '256'
disk        = [ 'phy:/dev/mapper/vg00-lv_freebsd,hda,w' ]
name        = 'xenfree.bsdsx.fr'
vif         = [ 'mac=00:16:3e:00:00:51,bridge=bridge0', 'mac=00:16:3e:00:01:51,bridge=bridge1' ]
on_poweroff = 'destroy'
on_reboot   = 'restart'
on_crash    = 'restart'
#extra       = 'console=hvc0,boot_verbose,kern.hz=100,vfs.root.mountfrom=ufs:/dev/md0p1'
extra       = 'console=hvc0,boot_verbose,kern.hz=100,vfs.root.mountfrom=ufs:/dev/ad0p2'

Pour conclure:

L'automatisation de l'installation peut se faire depuis un fichier /etc/rc que l'on aura pris soin de placer dans le ramdisk (attention à bien tout tester). Pour ma part, j'ai appris plein de trucs, donc mission accomplie :) Et cerise sur le gâteau, FreeBSD 9.1 est disponible !

Ps: les kernels sont disponibles ici.


Lien vers ce billet