Ceci est d’abord une prise de notes pour moi-même. Rédiger proprement ici me force à bien réfléchir à ce que je fais, et si ça peut servir à quelqu’un, hé ben tant mieux.

J’ignore dans quelle mesure ce qui suit diffère dans d’autres distributions.

Toute critique et avis sur comment mieux faire est bienvenue !

(Ajout de 2014 : Ce qui suit utilise la ligne de commande pour faire comme les grands. Ce qui importe ce sont les concepts, et pour gagner du temps on peut utiliser des interfaces graphiques : gparted pour le partitionnement, et system-config-lvm pour gérer la partie LVM. Ils font partie de toute distribution Linux digne de ce nom.)

Configuration d’origine

Linux Ubuntu 11.10 sur un Core Duo de 5 ans d’âge. Le disque de 1,5 To était partitionné en une seule partition /, contenant tout le reste, par paresse et facilité d'administration au départ, puis conservatisme lors des migrations suivantes. Le partitionnement est de type MBR, c’est-à-dire l’antique format MS-DOS.

Configuration cible

Je voulais remplacer ce disque devenu trop étriqué (ah, les films familiaux en DV…) par un 3 To vierge. Migrer d’un disque à l’autre, j’ai déjà fait (et décrit dans ces pages (déjà 3 ans ½ !!)), mais comme on le verra il y aura un gag au partitionnement.

Quitte à retailler les partoches, autant passer à LVM, ce que je voulais faire depuis longtemps. LVM permet de ne plus s’embêter avec les partitions, leur taille, leur emplacement : on attribue les partitions existantes à un « groupe de volumes » et on retaille là-dedans de vraies partitions que l’on étend au fur et à mesure des besoins et de gigaoctets réattribués au groupe. Par la suite, je jouerai peut-être avec du RAID ou des snapshots, enfin on verra.

Le gain en souplesse à long terme ne me semblait pas au départ valoir la peine d’investir du temps, j’ai changé d’avis.

Contraintes techniques

Le monde du PC se traîne en permanence des contraintes et normes remontant au XXè siècle, et mon PC n’est pas de la dernière fraîcheur bien que parfaitement adapté à ce que j’en fait encore, donc le dilemme est le suivant :

  • Partitionner en MBR (MS-DOS) ou en GPT (moderne) ?
    Garder le BIOS en IDE ou passer en AHCI ?
    La modernité plaide pour du partitionnement GPT, qui supporte parfaitement les disques de plus de 2 To avec un BIOS en AHCI. Cependant le vieux XP qui traîne encore sur un autre disque ne supporterait pas facilement le passage du BIOS en AHCI. De plus je ne sais pas trop comment ma vieille carte mère va réagir en bootant sur du GPT.
    Bref, je préfère garder le mode IDE et MBR pour le moment, par conservatisme, et je n’ai pas creusé plus loin.
  • Le problème du MBR est la limite des 2 To. En fait, cette limite est valable pour la taille d’une partition, ou pour son adresse de départ. On peut donc arriver à gérer presque 4 To en MBR en se débrouillant avec des partitions de moins de 2 To. Ce serait un problème si je voulais conserver la partition unique (je ne peux pas faire de partition de 3 To en MBR) ou encore si je voulais partitionner en mettant une grosse partition de, disons, 2,5 To pour /home en fin de disque.
    Mais puisque je vais utiliser LVM, je me fiche du partitionnement physique réel, il me suffit de couper en au moins deux partitions de moins de 2 To.
    Rappelons aussi que le MBR ne tolère pas plus de 4 partitions, dont une « étendue » qui en contient jusqu’à 32 autres.
  • Puis-je booter directement sur du LVM ? J’utilise cette horreur de Grub, pas le choix (mais je suis bien content qu’il soit là). Ma racine / peut être dans le LVM, OK. Par contre, ce n’est pas clair pour /boot où résident le kernel et l’image disque de démarrage.
    Par conservatisme et prudence, je créerai une partition /boot séparée, quitte à me compliquer un peu la vie : la mise en place d’une amorce est assez délicate comme ça pour ne pas pousser le soft dans ses retranchements.

Je laisse de côté

Sont mis de côté ou laissés en exercice au lecteur :

  • le disque de sauvegarde est un disque séparé, la copie se fait par le merveilleux rsnapshot, Time machine du pauvre ; ce disque sera purement et simplement déconnecté le temps de la manip ;
  • un système XP parallèle, qui chez moi est sur un petit disque séparé lui aussi, et même pas connecté d’ailleurs (c’est dire que je boote souvent dessus…) ;
  • le maniement de l’outil de partitionnement (j’aime bien parted et son pendant graphique gparted) ;
  • le détail de la copie des données vers le nouveau disque, ce qui suit étant adapté à ma configuration ;
  • le choix, le démarrage et le maniement du système intermédiaire qui sera utilisé à la création de l'amorçage (SystemRescueCD convient bien, n’importe quel LiveDVD d’Ubuntu ou Knoppix ira aussi je suppose).

Caveat lector / Warning / Achtung!

Il va sans dire que les sauvegardes doivent être à jour et de préférence sur un disque déconnecté du système ! Et ce même si je vais tout faire pour ne pas casser le système d’origine sur son disque, histoire de pouvoir revenir dessus si la tentative échoue.

Partitionnement

Comme dit, le disque de 1,5 To était utilisé en une seule partition /dev/sda1 de 1,5 To, partition de swap (inutilisée) mise à part.

root@poulain:~# di
Filesystem Mount Size Used Avail %Used fs Type
/dev/sda1 / 1,3T 1,2T 0,1T 92% ext4

Le nouveau de 3 To est installé en second disque, au moins le temps de la migration. Pour le moment il correspond à /dev/sdc.

Pour contourner les problèmes de MBR sur gros disques décrits ci-dessus, je crée :

  • une petite partition primaire de 2 Go pour le futur /boot (/dev/sdc1) ;
  • deux grosses partitions primaires de 600 Go (/dev/sdc2 et sdc3) qui iront alimenter le groupe de volumes ;
  • une grosse partition « étendue» de 1,7 To contenant le reste du disque ;
  • au sein de cette dernière, je crée /dev/sdc5 pour le swap (6 Go), même si j’utilise de moins en moins (swappiness de 10 chez moi) — dans une partition logique ce n’est pas gênant (je pourrais même prendre un fichier mais j’ai mes habitudes).

Vu que je ne sais pas trop ce que je ferai dans le futur, je préfère couper l’espace restant par « petite » tranche et ne pas tout prendre d’un coup :

  • /dev/sdc6 à sdc8 sont d’un quart de To chacune, là aussi pour le groupe de volumes ;
  • et je laisse le reste en jachère.

root@poulain:~# parted /dev/sdc
GNU Parted 2.3
Utilisation de /dev/sdc
Bievenue
(sic) sur GNU Parted! Tapez 'help' pour voir la liste des commandes.
(parted) print
Modèle: ATA Hitachi HDS72303 (scsi)
Disque /dev/sdc : 3001GB
Taille des secteurs (logiques/physiques): 512B/512B
Table de partitions : msdos

Numéro Début Fin Taille Type Système de fichiers Fanions
1 1049kB 2098MB 2097MB primary ext4
(pour /boot)
2 2098MB 631GB 629GB primary
3 631GB 1260GB 629GB primary
4 1260GB 3001GB 1740GB extended
(contient les suivantes)
5 1260GB 1267GB 6291MB logical linux-swap(v1)
6 1267GB 1529GB 262GB logical
7 1529GB 1791GB 262GB logical
8 1791GB 2053GB 262GB logical

Ajout d’octobre 2013 après que je me sois fait piéger : dans ce qui précède, on n’a pas encore atteint la limite des 2 Go en-dessous desquels doit se trouver le début d’une nouvelle partition (y compris logique au sein d’une étendue) puisque je suis resté dans une table de partitions MS-DOS. Donc la partition 9 devra aller directement jusqu’au bout du disque, sous peine que la partie libre à la fin reste inaccessible !

Déclaration à LVM des volumes physiques

On déclare comme suit les partitions que LVM va pouvoir utiliser. La mention du disque (sdc ici) m’a au début inquiété, mais LVM sait reconnaître ses petits même quand le disque change de lettre, car il y écrit ses propres métadonnées.

pvcreate /dev/sdc2 /dev/sdc3 /dev/sdc6 /dev/sdc7 /dev/sdc8

pvdisplay permet de consulter l’existant.

Création du pool

Je nomme LVMPOOL le groupe de volumes dans lequel je puiserais pour faire mes partitions, et je lui attribue les partitions initialisées ci-dessus :

vgcreate LVMPOOL /dev/sdc2 /dev/sdc3 /dev/sdc6 /dev/sdc7 /dev/sdc8

Création des partitions logiques

Je nomme RACINE, VAR, HOME les trois partitions logiques taillées dans LVMPOOL. Ce sont ces partitions qui porteront mes données et que le système montera. Je leur attribue respectivement 40 Go (ça suffira pour /, /usr, /root et quelques autres), 10 Go (il ne faut pas que /var gèle tout s’il explose), et 1,6 To à HOME :

lvcreate -L 40G -n RACINE LVMPOOL
lvcreate -L 10G -n VAR LVMPOOL
lvcreate -L 1600G -n HOME LVMPOOL

En fait il reste de la place, je peux l’attribuer à HOME avec une commande du genre :

lvextend -L +254280M /dev/LVMPOOL/HOME

Pour savoir s’il reste encore de la place, on demande à vgdisplay :

vgdisplay

vgdisplay Alloc PE / Size 485970 / 1,85 TiB
vgdisplay Free PE / Size 1525 / 5,96 GiB

...

J’ai donc encore 5,96 GiB de libre sur 1,85 TiB :

lvextend -L +5G /dev/LVMPOOL/HOME
lvextend -L +980M /dev/LVMPOOL/HOME

Les différentes partitions se retrouvent dans /dev/LVMPOOL même si les vrais noms sont /dev/dm-0 à dm-2 (que l’on n’utilisera pas) :

root@poulain:~# ls -l /dev/LVMPOOL/
total 0
lrwxrwxrwx 1 root root 7 2012-05-07 10:50 HOME -> ../dm-2
lrwxrwxrwx 1 root root 7 2012-05-07 10:50 RACINE -> ../dm-1
lrwxrwxrwx 1 root root 7 2012-05-07 10:50 VAR -> ../dm-0

Où et quoi ?

On peut se demander où se trouvent les données réellement puisqu’il s’agit de trois partitions virtuelles dans un espace qui regroupe cinq partitions réelles. Mais en fait ça n’a aucune importance !

Soit dit en passant, le dimensionnement des trois futures partitions pour /home, /var et de la racine est un peu pifométrique. Je pensais un temps faire aussi une partition pour /usr mais il faudrait aussi y mettre /lib, /bin, /opt… et ça devient pénible. Ou bien je scinderai le contenu de /home en fonction du contenu (films…) ou des utilisateurs. Si j’avais des partitions réelles, ce choix serait contraignant pour l’avenir ; mais avec LVM je peux retailler à volonté en puisant dans le groupe et en lui rendant les espaces excédentaires, et j’aviserai plus tard.

Le système de fichier

LVM ne fournit que des partitions et ne dispense pas de formater. Au passage : si on étend une partition logique, il faudra étendre aussi manuellement le système de fichiers (avec resize2fs par exemple).

Ici je choisis du ext4 classique. La partition (réelle) /dev/sdc1 (hors du groupe LVM) est le futur /boot. L’option -m règle la partie réservée à root dans le cas où la partition sature ; le défaut de 5% est du gaspillage vue la taille des disques actuels, le nouveau réglage est pifométrique.

mkfs.ext4 -m 0 -L HOME /dev/LVMPOOL/HOME
mkfs.ext4 -m 2 -L RACINE /dev/LVMPOOL/RACINE
mkfs.ext4 -m 5 -L VAR /dev/LVMPOOL/VAR
mkfs.ext4 -m 0 -L BOOT /dev/sdc1

Et ne pas oublier le swap, en le nommant, tant qu’on y est :

mkswap -c -L SWAP6GHITACHI3T /dev/sda5

Déclarer dans /etc/fstab

Pour transférer les données dans le nouveau LVM, il va falloir les déclarer dans le système actuel dans /etc/fstab. Penser à faire une sauvegarde de ce fichier critique avant…

Je monte les quatre partitions du futur système dans des sous-répertoires de /TESTLVM (à créer), on pourrait faire ça plus proprement dans /mnt mais c’est du détail.

Le noauto permet de ne monter ces partitions que sur demande (ordre mount explicite). L’identifiant (UUID) du futur /boot se trouve dans /dev/disk/by-uuid, j’aurais pu tout aussi bien mettre /dev/sdc1 si j’étais sûr que l’ordre de mes disques ne change pas.

# future racine
/dev/LVMPOOL/RACINE /TESTLVM/RACINE ext4 noauto,relatime,errors=remount-ro 0 1
# futur boot
UUID=b962392a-2232-4cac-aae0-3f50fefde3c2 /TESTLVM/BOOT ext4 noauto,relatime,errors=remount-ro 0 1
# LVM
/dev/LVMPOOL/VAR /TESTLVM/VAR ext4 noauto,relatime,errors=remount-ro 0 0
/dev/LVMPOOL/HOME /TESTLVM/HOME ext4 auto,relatime,errors=remount-ro 0 0

Ce qui donne au final après montage :

root@poulain:~# mount

/dev/sda1 on / type ext4 (rw,errors=remount-ro,commit=0)
/dev/mapper/LVMPOOL-RACINE on /TESTLVM/RACINE type ext4 (rw,relatime,errors=remount-ro)
/dev/mapper/LVMPOOL-VAR on /TESTLVM/VAR type ext4 (rw,relatime,errors=remount-ro)
/dev/mapper/LVMPOOL-HOME on /TESTLVM/HOME type ext4 (rw,relatime,errors=remount-ro)
/dev/sdc1 on /TESTLVM/BOOT type ext4 (rw,relatime,errors=remount-ro)

Recopie des données

Là arrive la partie la plus longue, et celle qui dépend le plus de la configuration précédente.

Chez moi tout était dans une seule partition, mais une installation plus propre aura par exemple une partition /home qu’on ne cherchera pas à migrer tout de suite. Ou bien, si le nombre de partitions d’origine est le même que celui de départ avec une taille identique, on pourra les copier brutalement avec dd. Bref, à voir au cas par cas. Je suis preneur de toute meilleure solution.

D’abord démonter tout ce qui n’est pas strictement nécessaire (clés, disques de sauvegardes…).

Puis créer sur le nouveau système les répertoires de base qui seront à monter plus tard :

cd /TESTLVM/RACINE
mkdir var home sys proc dev boot cdrom run tmp

Pour la recopie des données, je choisis rsync. Il y a peut-être moins bourrin ou plus rapide (un tar avec pipe ?). Mais rsync me permet de reprendre une copie partielle, ou de faire la copie en plusieurs fois, la source ayant changé entre temps (toute cette migration s’est déroulée sur plusieurs jours...).

On peut s’amuser préalablement à purger des logs ou /tmp ou /var/tmp ou des caches (apt-get clean par exemple) mais gagne-t-on au final beaucoup de temps ?

Si possible tout ce qui suit se fait en mode mono-utilisateur (init 1) mais j’ai préféré faire la première copie en mode classique car elle était longue, et relancer le script après le init 1 pour reprendre les quelques différences.

Dans les ordres suivants, l’option --one-file-system permet de ne pas sortir du système de fichier principal d’origine (car /proc, /dev, /sys, /run sont des systèmes de fichiers virtuels que l’on ne veut surtout pas copier, et potentiellement il pourrait y avoir des liens vers d’autres disques non affectés par la migration).

La difficulté est d’exclure /home et /var de la copie vers RACINE sans exclure des répertoires potentiellement nommés home (il y en a…) ou var (ou sys…) dans un sous-sous-répertoire. Ce qui suit devrait fonctionner mais… à vérifier !

Le fichier /etc/fstab est à exclure (et donc à copier manuellement en plus de ce qui suit) à moins d’être sûr de tout copier en une fois : je le modifierai sur la cible, je ne veux pas que la relance de ce script de copie l’écrase !

#!/bin/bash
# copie du contenu des partitions existantes vers lvm
# fstab est à gérer séparément a la main !
rsync -av -H --delete-during --one-file-system --exclude=/home --exclude=/var --exclude=/proc --exclude=/dev --exclude=/sys --exclude=/boot --exclude=fstab / /TESTLVM/RACINE
rsync -av -H --delete-during /var/* /TESTLVM/VAR
rsync -av -H --delete-during /boot/* /TESTLVM/BOOT
rsync -av -H --delete-during /home/* /TESTLVM/HOME

Modification du /etc/fstab de la cible

Quand l’ordinateur redémarrera sur le nouveau système il aura une autre vision du système. Donc on modifie comme suit le fstab dans /TESTLVM/RACINE/etc (ne pas modifier celui du système d’origine !).

#Ceci était dans /TESTLVM dans l’ancien système
/dev/LVMPOOL/RACINE / ext4 auto,relatime,errors=remount-ro 0 1
UUID=b962392a-2232-4cac-aae0-3f50fefde3c2 /boot ext4 auto,relatime,errors=remount-ro 0 1
/dev/LVMPOOL/VAR /var ext4 auto,relatime,errors=remount-ro 0 0
/dev/LVMPOOL/HOME /home ext4 auto,relatime,errors=remount-ro 0 0

# (optionnel) ancien système à monter en lecture seule pour consultation
UUID=bb92e08e-d94f-4dc6-bd3a-029df7e1ef7e /ANCIEN ext4 noauto,ro,errors=remount-ro 0 1

# swap (optionnel)
LABEL=SWAP6GHITACHI3T none swap pri=10,sw 0 0

Amorçage

Une fois que l’on est sûr que l’on a dupliqué les données nécessaires au nouveau système, il faut le rendre amorçable. C’est toujours l’étape la plus longue et pénible à débugguer, qui nécessite parfois de nombreux reboots, dévoile toutes les incompatibilités, et sanctionne chaque erreur d’un message abscons.

Pour être certain de ne pas toucher à l’amorçage de l’ancien système, je débranche carrément le disque dur.

Je boote sur SystemRescueCD (n’importe quel Live CD fera l’affaire). Du point de vue de ce système, mon nouveau disque dur est à présent /dev/sda, et les partitions LVM sont toujours dans /dev/LVMPOOL.

On monte les partitions nécessaires :

mkdir /mnt/nouveau
mount /dev/LVMPOOL/RACINE /mnt/nouveau
mount /dev/LVMPOOL/HOME /mnt/nouveau/home
mount /dev/LVMPOOL/VAR /mnt/nouveau/var
mount /dev/sda1 /mnt/nouveau/boot

La création de l’amorçage doit se faire du point de vue du système cible, donc il faudra y entrer par un chroot. Il y a quelques incantations préalables à cause des pseudo-systèmes de fichier qui doivent être accessibles :

mount -t proc none /mnt/nouveau/proc
mount -o bind /sys /mnt/nouveau/sys
mount -o bind /dev/mnt/nouveau/dev

Et c’est parti :

chroot /mnt/nouveau /bin/bash
grub-install /dev/sda
update-grub

La dernière commande liste les noyaux trouvés par grub dans /boot et les ajoute à l’amorçage.

Vérifier dans /boot/menu/grub.cfg (c’était menu.lst autrefois…), généré par l’ordre précédent, que les systèmes indiqués sont bons (en fouillant on y trouvera l’UUID de /boot et la mention de LVMPOOL-RACINE).

Normalement, un reboot sur le disque dur doit mener à l’affichage de grub et permettre d’amorcer le nouveau système.

Si on s’est trompé dans le fstab la sanction est immédiate, avec des messages plus ou moins clairs. Il faudra rebooter depuis SystemRescueCD.

Fin d’installation

À ce stade le nouveau système est utilisable.

On peut raccorder à nouveau l’ancien disque (je le monte ci-dessus dans /ANCIEN), au moins le temps de confirmer que tout fonctionne. Pour être certain de booter sur le nouveau et plus sur l’ancien système, changer l’ordre de démarrage dans le BIOS. Vérifier que l’on a bien rebooté sur le nouveau système en consultant le résultat de mount.

Si ce n’est déjà fait, activer le swap. Copier ou monter les éventuelles données de l’ancien système que l’on avait laissées de côté.

Tester les applications les plus importantes pour vérifier qu’il n’y a pas eu un hoquet quelque part.

Vérifier avec bonnie++ que le nouveau disque dur est plus rapide, et apprécier le gain de rapidité (probablement plus subjectif qu’autre chose).