Gentoo Linuxの Portageと呼ばれるパッケージ管理システムは、ソースコードをターゲットシステム上でビルドすることによりソフトウェアを提供するための柔軟な仕組みを提供しています。これは依存関係が複雑化した現代のソフトウェアを、古き良き UNIXの時代に行われていた(のに近い)やり方で利用するための妥当な折衷案として一部の(特にCコンパイラおよび周辺ツール群に親しみのある)中上級ユーザーに好まれており、そういった人々の存在が主に Gentoo Linuxの支持基盤となっています。

しかしながら、ターゲットシステム上でビルドを行うという性質上、ライブラリやツール類の進化による互換性の喪失と向き合わなければいけない機会が多いことは否めません。Portageの提供するパッケージはある程度の更新猶予期間を設けて互換性に配慮しているため、こまめにシステムをアップデートしていればそのような問題に遭遇することは少ないのですが、例えば年単位で更新を行わなかった場合などは、かなりの確率で更新が不可能になってしまう問題を抱えることになります。

要するに、Gentooは更新をサボっていると置いて行かれてハマるということです。

そういう状況で emergeコマンドによってシステムを更新しようとすると、およそ下記のようなことが起こります(シンプルな順)。

救済策として、chroot環境内に一時的な新しい Gentoo Linuxを作成し、それを利用して古い Gentoo環境を更新する方法が公式ドキュメントに載っています。 http://www.gentoo.org/doc/en/gentoo-upgrading.xml#old_system

と、ここまでが Gentoo Linux一般の話です。

Walbrix環境での救済方法

Walbrixは仮想マシンを運用するための環境ですから、上記公式ドキュメントにある方法を応用して「新しい Gentoo仮想マシンのイメージ」を用いて「古くなってしまった Gentoo仮想マシンのイメージ」を更新する方法を取ることができますのでここで紹介します。

古くて更新ができなくなってしまった仮想マシンを old-gentoo, 新しい仮想マシンを new-gentoo とすると、普通にインストールされた Walbrixでは下記のような論理ボリュームがそれぞれ存在しています。

両仮想マシンとも、作業前にシャットダウンされている必要があります。

稼働中の仮想マシンを Walbrix本体側からマウントして書き込みの発生する操作を行うと仮想マシンはほぼ確実に壊れます。やらないでください。

マウントとchroot

常にハードディスクの全体イメージを取り扱う完全仮想化と違い、Xenの準仮想化を利用する Walbrixでは仮想マシンを起動しなくても上記のボリュームを直接マウントするだけで中のファイルシステムにアクセス出来ます。Walbrixのコンソールに入るか、Walbrix本体に SSHでログインするなどして、下記のようにまずは new-gentooをマウントしてください。

mount /dev/wbvg/new-gentoo /mnt
mount --rbind /dev /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys /mnt/sys

/dev, /proc, /sysを --rbindでさらにマウントするのは、(善し悪しはともかく)パッケージによってはインストール時にそれらの場所から情報を得るものもたまにあるからです。

さらに、new-gentooの /mnt (つまり現在操作している Walbrix本体から見れば /mnt/mnt)に old-gentooをマウントして new-gentooから old-gentooを見られるようにします。

mount /dev/wbvg/old-gentoo /mnt/mnt

ここまで出来たら、new-gentooに chrootしましょう。chroot環境内で /mnt の中身を覗いてみて、old-gentooの内容が見られることを確認してください。

chroot /mnt
source /etc/profile
ls /mnt  # old-gentooの内容がここにあればOK

古いシステムを更新する

old-gentooの基本システムを更新します。普通に emergeすると現在の環境(つまり new-gentoo)を更新してしまうだけで意味がないので、emergeコマンドの前に常に ROOT=/mnt を付けることで対象が old-gentooだということを明示してやります。emergeのたびに ROOT=/mnt を書くのが面倒なら export ROOT=/mnt とだけ一度入力してやれば以降は省略できます。

更新を行う前に、emergeに pオプションを付けて、何か更新に不都合がないかまずは調べます。安心してください。だいたいあります。不都合。

ROOT=/mnt emerge -up system

old-gentooが古ければ古いほど、赤字で色々言われることでしょう。最新の Gentoo Linuxではもう使われなくなってしまいシステムに存在しているべきでないパッケージや、バージョン間で互換性が失われており存在してはいけないライブラリなどについては block 表示がされるので、そういうものは意を決して削除してしまいます。(下記はあくまで例なので自分の状況に合わせて判断してください。あと、ROOT=/mnt は絶対に忘れないでください)

ROOT=/mnt emerge --unmerge lzma-utils
ROOT=/mnt emerge --unmerge glibc
削除するものによっては「それをすてるなんてとんでもない、10秒以内に考えなおせ」と言われます。黙って 10秒放置してください。

負の遺産を削除し終わって衝突が解決したら、pオプションを外して実際の更新を実行します。年単位で更新を放置していた場合、ほぼ確実に gccや glibcといった大物の更新が入ってくるので時間に注意してください。それらが居る場合、食事に行って帰ってくるくらいの時間では済みません。

ROOT=/mnt emerge -u system

場合によってはシステムのヘッダファイルが古くてコンパイルエラーになってしまうパッケージもあるかもしれませんので、そういう場合は先に linux-headersを更新してみましょう。

ROOT=/mnt emerge -u linux-headers

どうしても何かで引っかかってコンパイルできないものがある場合、quickpkgコマンドで現状動作している新しい gentooからバイナリアーカイブを作ってしまうことでコンパイルせずにバイナリを古い gentooにインストールしてしまうこともできます。emergeコマンドに -kオプションを付けることで、バイナリアーカイブがあればそれをインストールしてくれるようになります。ただしこの方法でインストールしたパッケージが何かのライブラリに依存している場合、バージョンが合う保証はありません。

quickpkg --include-unmodified-config=y readline
ROOT=/mnt emerge -uk readline

chroot環境からの脱出とアンマウント

無事に基本システムの更新が終わったら、chroot環境を抜け出して old-gentooをアンマウントします。old-gentooが正常に起動することが確認できるまでは、new-gentooはまだマウントしたまま残しておく方が無難です。また戻ってくるかもしれないので。

exit
umount /mnt/mnt

更新された古いGentooの起動

この時点で(うまくいっていれば)old-gentooの基本システムが最新に更新されていますので、仮想マシンを起動して確認します。

xl create -c /etc/xen/old-gentoo
起動した仮想マシンのコンソールを抜けて Walbrix本体のコントロールに戻るには Ctrl+]を押します。

もし起動に問題がある場合、仮想マシンを停止(この場合かなりの確率で強制停止が必要ですが)した上で再度 old-gentooを new-gentooの /mntにマウントしなおして chrootし、必要な emergeを行ってください。

起動がうまくいっているようであれば、後は sshでログインしなおすなどして通常と同じように残りのパッケージを更新します。

libfoobar.laが無いっていうエラーでebuildが止まる場合、/usr/lib64以下あたりにある *.la のうち中に libfoobar.laの記述があるものを削除すると解決できる場合があります。

後片付け

Walbrix本体側でマウントした new-gentooをアンマウントして作業は完了です。

umount /mnt/dev
umount /mnt/proc
umount /mnt/sys
umount /mnt

必要なら new-gentoo 仮想マシンも起動してください。

xl create /etc/xen/new-gentoo