ttt

getttyent

FreeBSDをdisklessでiSCSIブートさせたいな

2015-04-02 22:59:44 | デジタル・インターネット

ちょっと前の話。
これまで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をつかってましたよね。あれ、どうやるんだったけかな。

あとで考えよう