ちょっと前の話。
これまでFreeBSD 9.xで使っていたマシンを、そろそろFreeBSD 10.xにしようと思ったけど、バージョンアップしたら動かなくなった、みたいなことになると困ります。
というわけで、FreeBSD 10をdisklessブートさせて、問題なく動作するか確かめてから、バージョンアップしようかな、ということにしました。
ファイルシステムをNFSで用意して、FreeBSDをdisklessでブートするのは、
https://www.freebsd.org/doc/handbook/network-diskless.html
Diskless Operation with PXE
にて説明してあることを、てきと~にはしょりながらやって、けっこう、かんたんにできてしまいます。
どうせなら、ファイルシステムをNFSではなくiSCSIにできたらいいんじゃね~?と思いまして、ちょっとやってみました。
ファイルシステムがNFSだと、chflagsができないので、freebsd-updateするとエラーになっちゃうんです・・・
root@HOST:~ # freebsd-update --debug install
Installing updates...install: rename: ///lib/INS@VZw2 to ///lib/libc.so.7: Operation not permitted
install: rename: ///sbin/INS@XLr3 to ///sbin/init: Operation not permitted
install: rename: ///usr/lib32/INS@LIyh to ///usr/lib32/libc.so.7: Operation not permitted
done.
だからiSCSIなら、普通のHDDと同じようにできますよね?、というわけです。
FreeBSD iSCSI bootとかでネット検索すると、iSCSIブートできるようにするコードを開発している人がおられるのですが、FreeBSD 9と書いてあったので、10だとどうなる???そもそも、そういうのは公式にサポートして欲しいな~、とか思いまして、今回はそちらはパス。
とりあえず、root filesystemをNFSとしてsingle user modeで起動して、
iscsid
とやってiSCSIしてみると、/var/run/iscsid.pid が作成できなくてエラー終了するので
iscsid -P /dev/null
としてみると、これならうまくいく
iscsictl -Aa
で、あー、iSCSIで見えました。
そこで、
mount -o rw,union /dev/gpt/rootFS /
したら(/dev/gpt/rootFS はiSCSIで見えるパーティション)、うまくいったように見えたのですが、viを起動したときkernel panic。
union FSてば、だめな子?
次のアイデア。
mount /dev/gpt/rootFS /mnt
mount_nullfs /dev /mnt/dev
chroot /mnt /bin/sh
sh /etc/rc
すると、/をmountしようとしてエラー終了する。
う~ん、/をrwマウントするタイミングで、まったく別のファイルシステムをマウントすることって、不可能なんですかね?
/etc/fstabで、/ の行はコメントアウト。もうマウントされているから不要だし、それがあるとエラーになるので。
sh /etc/rc
したらできた。
さて、どうやってマルチユーザーモードに移行するのだ?
・・・とか考えている間に、かってにリブートしていた。
kernel panicしていた。
mount_nullfsがいけないらしい。devfsをmountすればOK
こんな感じ
--------------
iscsid -P /dev/null
iscsictl -Aa
sleep 3
mount /dev/gpt/rootFS /mnt
mount -t devfs devfs /mnt/dev
swapon /dev/gpt/swapP
chroot /mnt /bin/sh
--------------
ということは
上記を/etc/rc.iscsiboot とかにしておいて、
/sbin/initが、最初にそれを実行し、
/sbin/initが、chrootしてしまえばいいのでは?
・・・という気がしてきました。
というわけで、/sbin/initのソースコードを見ますか。
このあたり使えそう。というか、それっぽいコードが書かれている!
if (kenv(KENV_GET, "init_script", kenv_value, sizeof(kenv_value)) > 0) {
state_func_t next_transition;
if ((next_transition = run_script(kenv_value)) != 0)
initial_transition = (state_t) next_transition;
}
if (kenv(KENV_GET, "init_chroot", kenv_value, sizeof(kenv_value)) > 0) {
if (chdir(kenv_value) != 0 || chroot(".") != 0)
warning("Can't chroot to %s: %m", kenv_value);
https://wiki.freebsd.org/AvgLiveCD
を読んでみたら、なんとなく、できました。
NFS rootとなる場所に、とりあえず、init_iscsiというファイル名で、こんなファイルを作っておく。
#!/bin/sh -vx
PATH=/sbin:/bin:/usr/sbin:/usr/bin
iscsid -P /dev/null
iscsictl -Aa
sleep 5
mount /dev/gpt/rootFS /mnt
mount -t devfs devfs /mnt/dev
swapon /dev/gpt/swapP
echo "init_iscsi done"
exit 0
同じくNFS rootとなる場所の/boot/loader.confにて、
init_script="/init_iscsi"
init_chroot="/mnt"
と書いておく。
これで、なんとなく動きました。
というわけで、こんな、ヘンテコなことをすれば、なんちゃってiSCSIブートができる!!
・・・う~ん、でも、最初にNFSを使ってるじゃん
1. 最初、ルートファイルシステムをNFSでマウントしてブートさせておいてから
2. iSCSIなファイルシステムをマウント
3. iSCSIなファイルシステムにchrootして、そこでinitを実行
問題点は、
freebsd-update install
したとき
iscsi側のファイルは置き換わるが、
NFS root側の
/sbin/init
が置き換わらない、ってこと。
/boot以下のファイルも、ブートローダでNFSなところを読みに行ってしまうので、portsでインストールしたものがあっても、反映されない。
うーん、MFSを使う方法が良さそうです。
そういえば、Linuxって、initramfsうんたら、でブートさせてるんですよね。
そんな感じのこと、FreeBSDでもできると思うのですが・・・
昔のFreeBSDのインストーラって、MFSをつかってましたよね。あれ、どうやるんだったけかな。
あとで考えよう