27/02/2010

Emprisonner une debian dans un FreeBSD

Parfois on a besoin de tester des choses sous linux, parfois on a besoin d'utiliser des applications linux-only, où pour tout un tas d'autre raison on a besoin de faire tourner un linux.

Pour ça c'est vrai que l'on peut virtualiser dans un virtualbox ou un qemu, c'est bien mais c'est quand même coûteux en terme de ressources pour le host.

Sous FreeBSD nous disposons du linuxulator c'est la couche d'emulation permettant de faire tourner des applications Linux sous FreeBSD.

Ni une ni deux je me dis qu'il est possible de faire de petites choses sympathiques avec ça : une jail linux-only.

Il faut d'abord préparer le terrain :

# mkdir /home/jails/debian
# mkdir /home/jails/debian/dev
# mkdir /home/jails/debian/proc
# mkdir /home/jails/debian/sys
# kldload linux
# kldload linprocfs
# kldload linsysfs
# kldload lindev
# mount -t devfs none /home/jails/debian/dev
# mount -t linprocfs none /home/jails/debian/proc
# mount -t linsysfs none /home/jails/debian/sys

Nous allons donc utiliser /home/jails/debian comme racine de la debian que nous allons installer.

Nous chargeons tous les pilotes nécessaires (notez que lindev est apparu en FreeBSD 9 et a été MFCed en 8-STABLE il n'est absolument pas obligatoire)

On pourrait faire l'installation avec debootstrap, mais comme je suis un feignant j'ai préféré utiliser un template openvz tout fait :

# fetch http://download.openvz.org/template/precreated/debian-5.0-x86.tar.gz

Puis le depacker dans ma jail :

# tar xvfp debian-5.0-x86.tar.gz -C debian --exclude dev* --exclude proc* --exclude sys*

Pour démarrer correctement la jail il faut qu'au minimum un service tourne dans la jail (je n'ai pas réussit à faire une jail linux-only persistente). Par défaut le script de démarrage des jails essaye de lancer /etc/rc que nous allons créer et de lancer /etc/rc.shutdown pour s'arrêter.

# echo "/etc/init.d/cron start" > /home/jails/debian/etc/rc
# chmod 755 /home/jails/debian/etc/rc
# echo "/etc/init.d/cron stop" > /home/jails/debian/etc/rc.shutdown
# chmod 755 /home/jails/debian/etc/rc.shutdown

dans /etc/rc.conf on règle le lancement de la jail

jail_debian_rootdir=/home/jails/debian
jail_debian_hostname="debian"
jail_debian_ip="192.168.1.3"
jail_debian_interface="nfe0"
jail_debian_devfs_enable="YES"
jail_debian_devfs_ruleset="devfsrules_jail"
jail_debian_flags="-n debian"

on démarre la jail :

# /etc/rc.d/jail start debian

et magie :

#jls
   JID  IP Address      Hostname                      Path
    15  192.168.1.3     debian                        /home/jails/debian
#jexec debian uname -a
Linux debian 2.6.16 FreeBSD 8.0-STABLE #3: Sun Jan 10 20:39:38 CET 2010 i686 GNU/Linux
#jexec debian cat /etc/debian_version
5.0.4

Vous voila avec une belle debian emprisonnée dans un freebsd.

Attention, tout ne fonctionne pas parfaitement : sysklogd ne marche pas à cause des accès /dev par exemple, mais c'est 99% fonctionnel quand même.

25/02/2010

Une jail 32bits sur un host 64bits

J'ai un eeepc 1000H qui fonctionne à merveille sous FreeBSD tout y est reconnu, juste un petite compilation maison pour le wifi, bref c'est pas le sujet de ce post.

Le truc c'est qu'un eeepc bah c'est lent pour la compilation, le binaire fournis par freebsd ne sont pas vraiment compilés avec les options que je souhaite, mais il s'avère que j'ai un beau Q6660 qui lui est plutôt très bien pour la compilation.

D'un autre côté je mijote toujours ma version FreeBSD de pkgin, du coup je me dis pourquoi pas compiler sur mon Q6600 les packages binaires depuis les ports et les installer via pkgin sur le 1000H, bah oui en voila une idée qu'elle est bonne.

De ce pas je me configure une jail 32bits (de la doc pour ça il y en a partout je vous laisse chercher :)) je me connecte dessus :

$ jexec eeepc /bin/sh

Je commence à compiler des ports, mais rapidement ça brotch de partout. Normal il me compile la moitié des choses en pensant avoir affaire à un amd64 :

$ uname -a
FreeBSD eeepc 8.0-STABLE FreeBSD 8.0-STABLE #3: Sun Jan 10 20:39:38 CET 2010     root@galway.lan:/usr/obj/usr/src/sys/GALWAY  amd64

C'est pas du tout, mais alors pas du tout la cible que je cherche, moi je veux build de l'i386, en suivant la branche RELEASE du kernel (pour les drivers venant des ports).

Réglons les problèmes un par un.

Tout d'abord faisons fonctionner freebsd-update afin de pouvoir avoir le dernier niveau de patch de la branche RELEASE

$ freebsd-update fetch
Looking up update.FreeBSD.org mirrors... 3 mirrors found.
Fetching metadata signature for 8.0-STABLE from update5.FreeBSD.org... failed.
Fetching metadata signature for 8.0-STABLE from update4.FreeBSD.org... failed.
Fetching metadata signature for 8.0-STABLE from update2.FreeBSD.org... failed.
No mirrors remaining, giving up.

C'est pas gagné pourtant j'ai bien installé un jail 8.0-RELEASE. Il me faut donc le lui faire savoir. Pour cela, il suffit de modifier le /etc/login.conf de la jail et remplacer :

:setenv=MAIL=/var/mail/$,BLOCKSIZE=K,FTP_PASSIVE_MODE=YES:\

par

:setenv=MAIL=/var/mail/$,BLOCKSIZE=K,FTP_PASSIVE_MODE=YES,UNAME_m=i386,UNAME_p=i386,UNAME_r=8.0-RELEASE-p2,OSVERSION=800107,UNAME_v=FreeBSD 8.0-RELEASE-p2:\

Une recontruction de la db est nécessaire :

$ cap_mkdb /etc/login.conf

On peut maintenant quitter l'environnement et se reconnecter à la jail, par contre pour forcer la prise en compte de login.conf il faut forcer l'utilisateur dans la ligne jexec du coup :

$ jexec -U root eeepc /bin/sh
$ uname -a
FreeBSD eeepc 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 i386

Parfait, maintenant relancez freebsd-update vous verrez qu'il fonctionne correctement.

Second problème les ports, là il en faut un peu plus.

En effet les ports vont chercher l'architecture via le sysctl :

Là notre astuce ne fonctionne plus, de plus il est impossible de les changer depuis une jail. Du coup en cherchant un peu dans /usr/ports/Mk/*.mk on se rend vite compte que l'on peut contourner le problème via /etc/make.conf. Pour ça, il suffit de rajourer les variables suivantes :

MACHINE=i386
MACHINE_ARCH=i386

Désormais je peux tout compiler tranquilement depuis ma jail et utiliser les packages sous mon eeepc. Afin de gagner en simplicité j'utilise ma version maison de pkgin (oui un jour elle sera intégrée upstream), en générant un INDEX.bz2 de la liste de mes packages et en mettant ça à dispo sur un serveur web par exemple

PS: pour générer l'INDEX.bz2, j'ai fait un petit prog en C: pkg_index, il n'est pas aussi complet que l'INDEX.bz2 normal mais beaucoup plus simple à utiliser et suffisant pour pkgin.

$ ./pkg_index /usr/ports/packages

PS2: pour créer mes packages j'utilise portmaster c'est moins lourd qu'une tinderbox

$ portmaster -ag

25/11/2009

Convertir l'arbre CVS des ports en git (round 2)

Il y a quelques mois je cherchais tranquillement à convertir l'arbre cvs des ports FreeBSD en arbre git.

Ça avait bien marché, mais il y avait deux inconvénients majeurs :

Et puis hier, gaston me montre ça nonchalamment, puis ça, bon j'y crois pas trop mais je me lance

Récupération du CVSROOT

Créer le fichier de config suivant pour csup

*default host=cvsup.free.org
*default base=/var/db
*default prefix=/usr/portsdev/cvsroot
*default release=cvs
*default delete use-rel-suffix

*default compress

ports-all

Puis récupérer le cvsroot :

$ csup cvsroot-supfile

Installation des pré-requis

Installation des packages

$ make -C /usr/ports/devel/mercurial install clean
$ make -C /usr/ports/lang/ruby18 install clean
$ make -C /usr/ports/textproc/ruby-iconv install clean
$ make -C /usr/ports/devel/ruby-rbtree install clean

Installation de rcsparse

$ hg clone http://ww2.fs.ei.tum.de/~corecode/hg/rcsparse
$ cd rcsparse 
$ ruby extconf.rb
$ make
$ make site-install

Récupération des sources de fromcvs

$ hg clone http://ww2.fs.ei.tum.de/~corecode/hg/fromcvs

Conversion du CVSROOT en git

Préparation du répertoire de destination

$ mkdir /usr/portsdev/freebsd-ports.git
$ cd /usr/portsdev/freebsd-ports.git
$ git init --bare

Conversion

$ cd /usr/portsdev/fromcvs
$ ruby togit.rb /usr/portsdev/cvsroot ports /usr/portsdev/freebsd-ports.git

2h30 (oui seulement 2h30 !!! ) après c'était fait

Le répertoire de destination fait 720Mo.

Repack du rep

$ cd /usr/portsdev/freebsd-ports.git && git repack -a -f -d

Ce coup ci ça ne dure que 5 petites minutes et le répertoire ne fait plus que 410Mo

Mise à jour de l'arbre git

Comme fromcvs fonctionne de manière incrémentale, il faudra juste relancer le csup de temps en temps et relancer la commande togit.rb pour faire très rapidement les mises à jours

Bilan du round 2

fromcvs n'est pas parfait (il n'importe pas encore les tags) en revanche il a été capable de me conserver plus de branches que ce que parsecvs avait fait, en plus il est beaucoup, beaucoup, beaucoup plus rapide :

Pour les ports la conversion passe de 17h30 à 2h30 le repack passant lui de 28h50 à 5min, la taille du repos avant repack de 4go à 710Mo.

Par contre attention togit.rb est un très gros consommateur de RAM : il a bouffé mes 4Go de RAM plus 3Go de SWAP pour convertir les ports !!!

La mise à jour fonctionne parfaitement. Autant dire que je garde cette méthode. J'ai bien essayé de modifier fromcvs afin qu'il puisse importer les tags, mais je n'y suis pas arrivé, le ruby ne m'aime définitivement pas.

27/10/2009

VirtualBox sur un hôte FreeBSD

Au boulot pour les mails, nous utilisons Br0tchus Notes, un espèce de daube infâme qui te pique ta ram pire qu'un firefox dans ces mauvais jours, bref.

Mon problème c'est que mon Desktop c'est du FreeBSD et que les gens de chez IBM, il ne fournissent de clients que pour Linux (si on ne considère que les environnements libre) - le java ça ne devait pas permettre de faire des applis qui tourne chez tout le monde ??? (oui il y a des vrais morceaux d'eclipse donc de java dans les derniers clients Notes)... bref -

VirtualBox ayant été porté récemment sous FreeBSD avec le support des extensions Vt-X je me suis donc lancé dans la virtualisation d'une debian minimaliste qui n'aura pour seul but que de lancer le client Notes et de le confiner en RAM afin qu'il ne me pique pas tout ce que j'ai de disponible sur ce Desktop.

Pour cela je l'ai donc installé depuis les ports (il faudra faire attention pour lancé les VMs à bien avoir mounté /proc - oui le ports n'est pas encore super propre, mais on fera avec). Comme c'est déjà super long à compiler je l'ai compilé en enlevant le support QT4, en effet la GUI n'apporte pas grand chose à cette application et en plus elle ne permet pas d'accéder à des fonctionnalités intéressantes de VBox.

Pour finir afin d'être plus souple j'ai utilisé les volumes zfs comme disques pour l'invité.

Installation de virtualbox

$ make -C /usr/ports/emulators/virtualbox config

Choisissez les options qui vous plaisent

$ make -C /usr/ports/emulators/virtualbox install clean

Si tout ce passe bien vous disposez maintenant de virtualbox sur votre machine.

Préparation du disque d'accueil de l'invité

Règle devfs

Pour que les volumes pour l'invité puisse être modifié par l'application virtualbox, ils doivent appartenir au groupe vbox, devfs nous permet de le faire à la volée, pour cela, dans le fichier /dev/devfs.rules :

[localrules=1]
add path 'zvol/vbox/*' mode 0660 group vbox

Ne pas oublier de modifier /etc/rc.conf pour qu'il le prenne en compte :

devfs_system_ruleset="localrules"

Un petit redémarrage de devfs pour finir :

$ /etc/rc.d/devfs restart

Création du volume

5G suffirons largement pour notre installation et encore je suis très large

$ zfs create -V 5G vbox/debian

Nous disposons maintenant d'un disque qu'il ne reste plus qu'à ajouter au pool de disques VirtualBox :

$ VBoxManage internalcommands createrawvmdk -filename melebian.vmdk -rawdisk /dev/zvol/vbox/debian
$ VBoxManage registerimage disk debian.vmdk

Création de la machine virtuelle

Création de la VM sans disque

Nous allons donc créer la VM pour qu'elle support les extensions VT-x et qu'elle soit limitée à 256Mo de RAM il ne s'agirait pas non plus que notes se sente trop à son aise.

$ VBoxManage createvm -name debianVM -register
$ VBoxManage modifyvm debianVM --ostype debian -memory 256M
$ VBoxManage modifyvm debianVM --vtxvpid on

Nous allons aussi déporter le port 22 de l'invité sur le port 2222 local afin de se simplifier la tâche pour le réseau (on laisse le réseau par défaut de virtualbox)

$ VBoxManage setextradata debianVM "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/GuestPort" 22
$ VBoxManage setextradata debianVM "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/HostPort" 2222
$ VBoxManage setextradata debianVM "VBoxInternal/Devices/pcnet/0/LUN#0/Config/ssh/Protocol" TCP

Ajout du disque à la nouvelle VM et de l'iso de l'installeur

Tout d'abord on liste les disques disponibles dans le pool pour récupérer son identifiant :

$ VBoxManage list hdds
UUID:         b6db4102-90fd-4073-ae61-c1c57556bb85
Format:       VMDK
Location:     /home/bapt/debian.vmdk
Accessible:   yes

Il suffit maintenant de le rajouter :

$ VBoxManage modifyvm debianVM -hda b6db4102-90fd-4073-ae61-c1c57556bb85

On enregistre l'iso dans le pool VirtualBox :

$ VBoxManage registerimage dvd /home/bapt/Desktop/debian-501-i386-netinst.iso

Et on l'ajoute de la même manière à la VM

$ VBoxManage list dvds
UUID:       b3329255-221a-4bb6-b1f4-be2d4bdc0f2f
Path:       /home/bapt/Download/debian-501-i386-netinst.iso
Accessible: yes

$ VBoxManage modifyvm debianVM -dvd b3329255-221a-4bb6-b1f4-be2d4bdc0f2f -boot1 dvd

Installation de l'invité

Pour l'installation de l'invité, on démarrera en mode sdl pour la suite ça ne sera plus nécessaire :

$ VBoxManage startvm debianVM --type sdl

Ou

$ VBoxSDL startvm debianVM

il ne vous reste plus qu'à faire votre installation debian normale à laquelle vous ajouterez votre client br0tchus notes et le configurerez.

afin que votre VM puisse accéder au disque de l'hôte sans se prendre la tête, VirtualBox prévoie un mécanisme bien sympathique :

$ VBoxManage sharedfolder add debianVM -name share -hostpath /home/bapt/sharedvm

Pour y accéder depuis votre debian, il faudra installer les guestutils

$ apt-get install virtualbox-ose-guest-modules virtualbox-ose-guest-utils

Puis dans le /etc/fstab de l'invité

share            /home/bapt/sharedHost    vboxsf  uid=bapt,gid=bapt       0       0

Maintenant lorsque vous démarrerez votre VM vous le ferez de la manière suivante :

$ VBoxManage startvm debianVM --type headless 

Ou

$ VBoxHeadless startvm debianVM

Et pour se connecter à la VM depuis l'hôte :

$ ssh -Y -p 2222 bapt@localhost 

lancez notes ou votre application désirée.

Comme je suis un gentil lutin j'ai partagé tout ça de manière plus générique sur GCU

28/08/2009

Reconstruire les paquets cassés

Voici un petit script ZSH pour rechercher les binaires systèmes qui ne trouvent pas les bibliothèques dont ils dépendent et les reconstruire en utilisant portmaster.

#!/usr/local/bin/zsh

typeset -a torebuild

rep=(/usr/local/bin/**/*(.))
rep+=(/usr/local/lib/**/*.so(.))
rep+=(/usr/local/sbin/**/*(.))

for bin ($rep) {
    file $bin | grep -q "ELF" && {
        ldd =$bin | grep -q "not found" && {
            torebuild+=$(pkg_info -qoW $bin)
        }
    }
}
portmaster -f ${(u)torebuild}

27/08/2009

Convertir l'arbre CVS des ports en git

Voulant pouvoir jouer tranquillement avec les ports via git, je me suis dit que j'allais convertir les CVS des ports en git tout simplement.

Récupération du CVSROOT

Créer le fichier de config suivant pour csup

*default host=cvsup.free.org
*default base=/var/db
*default prefix=/usr/portsdev
*default release=cvs
*default delete use-rel-suffix

*default compress

ports-all

Puis récupérer le cvsroot :

$ csup cvsroot-supfile

Récupération et construction de parsecvs

Récupérer les sources

$ git clone git://anongit.freedesktop.org/~keithp/parsecvs

Contruire les lib git qui seront nécessaires, sans les installer.

$ make -C /usr/ports/devel/git

Modifier le Makefile de parsecvs pour qu'il ressemble à celui-ci

GCC_WARNINGS1=-Wall -Wpointer-arith -Wstrict-prototypes
GCC_WARNINGS2=-Wmissing-prototypes -Wmissing-declarations
GCC_WARNINGS3=-Wnested-externs -fno-strict-aliasing
GCC_WARNINGS=$(GCC_WARNINGS1) $(GCC_WARNINGS2) $(GCC_WARNINGS3)
GITPATH=/usr/ports/devel/git/work/git-1.6.4
CFLAGS=-O2 -g $(GCC_WARNINGS) -I$(GITPATH) -DSHA1_HEADER='<openssl/sha.h>' -I/usr/local/include
LIBS=-L$(GITPATH) -lgit $(GITPATH)/xdiff/lib.a -lssl -lcrypto -lz -liconv -L/usr/local/lib
YFLAGS=-d -l
LFLAGS=-l

OBJS=gram.o lex.o parsecvs.o cvsutil.o revdir.o \
        revlist.o atom.o revcvs.o git.o gitutil.o rcs2git.o \
        nodehash.o tags.o tree.o

parsecvs: $(OBJS)
        cc $(CFLAGS) -o $@ $(OBJS) $(LIBS)

$(OBJS): cvs.h
lex.o: y.tab.h

lex.o: lex.c

y.tab.h: gram.c

clean:
        rm -f $(OBJS) y.tab.h gram.c lex.c parsecvs
install:
        cp parsecvs edit-change-log ${HOME}/bin

Construction et installation de parsecvs

$ gmake
$ cp parsecvs edit-change-log /usr/local/bin

Conversion du CVSROOT en git

$ cd /usr/portsdev/ports

Si vous utilisez zsh :

$ print -l **/*,v | parsecvs

Sinon

$ find . -name "*,v" -print | parsecvs

Attention c'est long, très long : 17h30 sur un Q6600 avec 4Go de RAM et un disque SATA 150 en zfs Le facteur principal est la vitesse du disque dur en effet la consommation de RAM et CPU est négligeable comparée à l'utilisation disque.

Une fois cette étape terminée vous disposez d'un répertoire git fonctionnel mais énorme : plus de 4Go

Repack du rep

$ git repack -a -f -d -l

Cette étape est très longue aussi et dépend de la vitesse de votre disque pour beaucoup. Ici ça a pris 28h50

Une fois cette étape finie vous voila avec un répertoire git de 400M ce qui est quand même beaucoup mieux.

Préparation pour les mises à jour

Alors comme cvsps foire prodigieusement souvent via git cvsimport, il faut le lancer de côté :

$ export CVS_RSH=ssh
$ export CVSROOT=anoncvs@anoncvs.fr.FreeBSD.org:/home/ncvs
$ cvsps -x --norc -u -A ports > /tmp/cvsps.out

Mise à jour de l'arbre git

$ git cvsimport -o master -P /tmp/cvsps.out ports

Vous voila avec un git à jour, pour continuer à mettre à jour, recommencer les deux dernières étapes.

En un seul coup pour zsh :

$ git cvsimport -o master -P <(cvsps -x --norc -u -A ports) ports

27/08/2009

zcp un wrapper pour cp

L'autre jour sidh me demandait si je n'avais rien en zsh pour pouvoir suivre la progression d'un cp volumineux et je n'avais rien, mais j'ai trouvé l'idée intéressante. Un petit man cp plus tard, je me rend compte que le cp de FreeBSD il est beau et bien foutu, en lui envoyant un SIGINFO il nous dis ce qu'il fait et ou il en est. De là a wrapper tout dans un petit script zsh il n'y avait qu'un pas.

De plus zsh permet de créer un tty virtuel (zpty) dans lequel on peut exécuter des commandes et interagir, du coup, voici un petit script bien pratique :

#!/usr/local/bin/zsh
setopt extendedglob
zmodload zsh/zpty
zpty copy "cp $@ 2>&1"     
ZPTYPID=${${=${(M)${(f)"$(ps -o pid,ppid,command)"}:#[[:space:]]#[[:digit:]]##[[:space:]][[:space:]]#$$*zsh*}}[1]}
CPPID=${${=${(M)${(f)"$(ps -o pid,ppid,command)"}:#[[:space:]]#[[:digit:]]##[[:space:]][[:space:]]#${ZPTYPID}*cp*}}[1]}
line=""
while [ : ]
do
    zpty -rt copy out
    if [[ $#out -gt 0 ]]
    then
        newline=${${=${out}}[0,-2]}
        percent=${${=${out}}[-1]}
        if [[ -z $line || "x$newline" != "x$line" ]]
        then
            [[ -n $line ]] && print "${line}: done"
            line=$newline
            print "${line}: ${(l: ::4:)percent}\c"
        else
            print "\r${line}: ${(l: ::4:)percent}\c"
        fi
    fi
        kill -SIGINFO $CPPID 2>/dev/null || break
done
[[ -n $line ]] && print "${line}: done"
zpty -d copy

la sortie donne : # zcp toto.iso bla/ toto.iso -> bla/toto.iso: 48%

UPDATE: Apparemment ça ne fonctionne qu'avec zsh 4.3.10+

11/06/2009

Zsh avec Ncurses c'est beau

Depuis un moment déjà zsh a un nouveau module zsh/curses qui permet de faire de belles interface en ncurses directemet en script zsh. Depuis le temps que je voulais essayer, j'ai fini par me décider.

Pour mon premier bout de zsh/curses, j'ai décider de me faire un mixer tout joli utilisant mixer(8), je m'inspire donc de rexima dont j'aime bien l'ui et je suis donc parti pour me faire un zmixer.

De plus j'ai découvert que l'on pouvais faire du ZSH avec une syntaxe "un peu objet" alors voila le code obtenu :

#!/usr/bin/env zsh

zmodload zsh/curses

zmix()
{
    local mixer
    local -a zmix_dev
    integer y
    integer posy
    integer length
    #get list of devices
    zmix.draw()
    {
        zcurses addwin main $(( $LINES - 2 )) $(( $COLUMNS - 2 )) 1 1
        title="zmixer"
        zcurses move main 1 $(( ($COLUMNS - 2 - $#title) / 2 ))
        zcurses string main $title
        y=4
        for dev ($zmix_dev);do
            y+=1
            zcurses move main $y 5
            zcurses string main $dev
            zcurses move main $y 15
            zcurses string main ":"
            # Set the recording device
            if [[ "x$dev" = "x$record" ]]; then
                zcurses addwin record 1 1 $(( y + 1 )) 4 main
                zcurses attr record red/black bold
                zcurses string record "*"
            fi
            level=${${(f)"$(/usr/sbin/mixer -s $dev)"}[(w)2]}
            numlevel=${${(s#:#)level}[1]}
            zcurses move main $(( y )) 17
            line="|"
            zcurses string main "[${(r:$length::-:)${(l:$(( numlevel / 2))::=:)line}}] ($level)"
        done
        if (( posy == 0 ));then
            posy=5
        fi
        zmix.sel $posy
        zcurses refresh main
    }
    zmix.listen()
    {
        while true;do
            if [[ -z $key ]];then
                zcurses input main REPLY key
            fi
            newkey=$key
            key=
            case $newkey in
                (UP)
                if (( posy <= 5 )); then
                    zmix.sel $y
                else
                    zmix.sel $(( posy - 1 ))
                fi
                ;;
                (DOWN)
                if (( posy >= y )); then
                    zmix.sel 5
                else
                    zmix.sel $(( posy + 1 ))
                fi
                ;;
                (LEFT)
                dev=$zmix_dev[$(( posy - 4 ))]
                mixer $dev -1 2>&1 >/dev/null
                zmix.redraw $dev
                ;;
                (RIGHT)
                dev=$zmix_dev[$(( posy - 4 ))]
                mixer $dev +1 2>&1 >/dev/null
                zmix.redraw $dev
                ;;
                ("")
                if [[ -z $REPLY ]];then
                    zcurses delwin record
                    zcurses delwin main
                    zcurses clear stdscr redraw
                    zcurses refresh stdscr
                    zmix.draw
                else
                    break
                fi
                ;;
            esac
        done
    }
    zmix.sel()
    {
        zcurses move main $posy 0
        zcurses string main "  "
        posy=$1
        zcurses move main $posy  0
        zcurses string main "->"
        zcurses refresh main
    }
    zmix.redraw()
    {
        dev=$1
        level=${${(f)"$(/usr/sbin/mixer -s $dev)"}[(w)2]}
        numlevel=${${(s#:#)level}[1]}
        zcurses move main $posy 16
        zcurses clear main eol
        level=${${(f)"$(/usr/sbin/mixer -s $dev)"}[(w)2]}
        numlevel=${${(s#:#)level}[1]}
        zcurses move main $posy 17
        line="|"
        zcurses string main "[${(r:$length::-:)${(l:$(( numlevel / 2))::=:)line}}] ($level)"
        zcurses move main $posy 2
        zcurses refresh main
    }
    #Constructor
    {
        length=50
        mixer=(${=${(f)"$(/usr/sbin/mixer -S)"}})
        for line ($mixer);do
            [[ -n ${line:#*:*:*} ]] && continue
            zmix_dev+=${${(s#:#)line}[1]}
        done
        record=$mixer[$#mixer]
        zcurses init
        zmix.draw
        zmix.listen
    } always
    {
        #cleanup all windows
        for win ($zcurses_windows);do
            [[ -z ${win:#(main|stdscr)} ]] && continue
            zcurses delwin $win
        done
        zcurses delwin main
        zcurses end
    }
}
zmix

Je sais pas vous mais moi je trouve ça beau.

Le résultat en image :

zmixer

EDIT: Promis dès que ça sera plus propre ça ira dans zen

27/05/2009

Migrer sur du Full ZFS

Depuis peu : les derniers commit en -STABLE ont eu lieu ce WE, il est possible d'avoir un FreeBSD 100% en ZFS, avant il y avait une solution qui consistait à passer ses disques du format MBR au format GPT, mais nous pouvons maintenant le faire directement sur du MBR.

De plus il est possible de booter sur des RAID-Z ou des MIRROR zfs.

Attention : la manipulation suivante doit se faire avec un système 7-STABLE ou 8-CURRENT très récent, de plus il faut rajouter l'option LOADER_ZFS_SUPPORT=YES dans le /etc/src.conf ou /etc/make.conf suivant les goûts afin que le loader sache travailler sur du ZFS.

Dans le cas présent nous allons donc migrer un système FreeBSD-Current tout frais mono-disque d'une installation UFS vers ZFS. Dans mon cas je voulais changer le disque dur au passage donc tout est parfait.

Création du POOL

Après avoir ajouter le disque (ici ad6) dans la machine, et de l'avoir vidé de toutes ses éventuelles partitions, nous allons créer notre zpool, il est donc possible ici de faire du mirror ou des raidz :

$ zpool create tank ad6
$ zpool export tank

Ajout de ZFSBOOT dans le mbr

$ dd if=/boot/zfsboot of=/dev/ad6 bs=512 count=1
$ dd if=/boot/zfsboot of=/dev/ad6 bs=512 skip=1 seek=1024

Si vous voulez booter sur un mirror zfs n'oubliez pas de faire la même chose sur l'autre disque.

Réactivation du pool

$ zpool import tank

Vous pouvez maintenant créer tous les FS que vous voulez dedans. attention si vous décidez de créer des FS spécifique pour /usr ou /var, vous devrez changer le mountpoint après un reboot en mode single sur le nouveau disque ZFS.

dans mon cas j'ai créé un swap de 1G :

$ zfs create -V 1g tank/swap
$ zfs set org.freebsd:swap=on tank/swap

La dernière option permet d'activer le swap automatiquement au boot lors de l'activation du zpool tank.

Et comme les checksum ça sert à rien sur du swap :

$ zfs set checksum=off tank/swap

migration des données

Pour migrer les données vous avez tout le choix des outils habituels, dans mon cas j'ai pris rsync ce coup ci et j'y suis allé gaiement à coup de rsync, par exemple :

$ rsync -av /boot /tank
$ ...
$ rsync -av /var /tank

En ne migrant pas bien entendu /dev ou autre FS "particulier".

Finalisation

pour finir il faut vous assurez que

si ce dernier n'y est pas ou que vous voulez le recréer par précaution :

$ zpool export tank && zpool import tank
$ zfs mount -a
$ cp /boot/zfs/zpool.cache /tank/boot/zfs/zpool.cache

Si tout ça est bon, il ne nous reste plus qu'à préciser à votre zfs quel est votre FS de boot

$ zpool set bootfs=tank tank

et Enfin de ne pas spécifier de point de montage pour tank :

$ zfs set mountpoint=legacy tank

c'est bon vous pouvez redémarrer sur le nouveau disque en 100% ZFS et supprimer votre disque UFS.

18/04/2009

Changer le disque système sur FreeBSD

La manipulation suivante a été faite sur un FreeBSD 8-CURRENT récent "kern.osreldate: 800074" Je ne sais pas si elle fonctionne sur les versions 7.x out of box. Qui plus est gjournal pour la partition / pose des soucis sur les freebsd plus vieux que FreeBSD 7.2.

La disque système de ma machine commençait à faire des siennes dessus il y avait mon / et mon /home le reste était réparti sur les autres disques durs.

Je voulais donc changer de disque dur sans me prendre la tête (ie sans livecd, sans réinstaller) Comme c'est une machine perso je ne me suis pas pris la tête sur le partitionnement, le disque faisant 80Gio j'ai mis :

J'ai donc rajouté un disque de la même taille sur la machine (il m'en restait un qui traînait dans un coin), enfin n'importe quel disque aurait pu faire l'affaire.

Une fois la machine bootée je me retrouve avec mon nouveau disque (ad2) et mon ancien disque (ad3)

Préparation du disque ad2

Pour le fun je me suis dis que j'allais partitionner mon disque au format GPT, puisque c'est à la mode (ça sert à rien dans mon cas, mais je voulais jouer avec)

j'ai donc détruit le partionnement existant :

$ gpart destroy ad2

Puis recréer en précisant le système de partitionnement GPT

$ gpart create -s GPT ad2

Une vérification que tout c'est bien passé :

$ gpart show
=>       34  156301421  ad2  GPT  (75G)
    	 34  156301421        - free -  (75G)

Les BIOS classiques ne sont pas capable de booter sur du GPT, mais sous FreeBSD il y a une astuce qui marche impeccable

$ gpart add -b 34 -s 16 -t freebsd-boot ad2
$ gpart bootcode -b /boot/pmbr ad2
$ cp /boot/gptboot /tmp
$ dd if=/dev/zero bs=641 count=1 &gt;&gt; /tmp/gptboot
$ dd if=/tmp/gptboot of=/dev/ad2p1 bs=512

ainsi le système est bootable;

j'ai plus qu'à recréer mes partitions

$ gpart add -b 50 -s 20971520 -t freebsd-ufs ad2
$ gpart add -b 20971570 -s 4194304 -t freebsd-swap ad2
$ gpart add -b 25165874 -s 131135581 -t freebssd-ufs ad2

Vérification :

$ gpart show
=>       34  156301421  ad2  GPT  (75G)
	 34         16    1  freebsd-boot  (8.0K)
	 50   20971520    2  freebsd-ufs  (10G)
   20971570    4194304    3  freebsd-swap  (2.0G)
   25165874  131135581    4  freebsd-ufs  (63G)

maintenant j'active le gjournal pour les partitions ufs

$ gjournal label /dev/ad2p2
$ gjournal label /dev/ad2p4

On format le tout (pour rappel sous freebsd pas besoin de formatter les partitions swap

$ newfs -J -L root /dev/ad2p2.journal
$ newfs -J -L home /dev/ad2p4.journal

Le -L signifie que l'on écrit un label ainsi les partitions sont facilement montable grâce à GLABEL qui les représente sous la forme : /dev/ufs/LABEL

Migration des données

maintenant il s'agit de migrer le contenu des partitions / et /home sur les nouvelles le tout à chaud :

$ mkdir /newroot
$ mount -o async /dev/ufs/root /newroot
$ cd /newroot
$ dump -0uanL -f - / | restore -rf -
$ mkdir /home2
$ mount -o async /dev/ufs/home /home2
$ cd /home2
$ dump -0uanL -f - /home | restore -rf -

il faut pour finir modifier la fstab du nouveau root pour rajouter :

Le fichier /etc/fstab obtenu est donc :

# Device		Mountpoint	FStype	Options		Dump	Pass#
/dev/ad2p3		none		swap	sw		0	0
/dev/ufs/root		/		ufs	rw,async	1	1
/dev/ufs/bapt		/home	ufs	rw,async	1	1

Il ne reste plus qu'à rebooter dessus.

Pages : 1 2 3