NanoBSDで WANエミュレータ
最初はライブカメラを作るつもりで準備をしていたのだが、 ひょんな事からちょっと脱線して WANエミュレータを作ってみることにした。
下調べの結果、仕込むべきネタは dummynet + ipfw + bridgeで、 ipfwが dummynetのさまざまなパラメータを渡すための UIになっているみたい。
今回は帯域(bandwidth)と遅延(delay)を制御できればとりあえず OKなんだけど、 パケットロスの確率(plr)とかも制御できたりするらしい。
例によってググった結果、 とてもわかりやすい解説 (感謝!!) が見つかったので、それを元に NanoBSD特有の事情を組み合わせて作ってみた。
実は自分にとっての今回のポイントは、 ↑のページのおかげで、ブリッジの作成そのものよりも、 ブリッジ用にカスタマイズした NanoBSDのイメージを、 動作中の NanoBSD boxにインストールする環境を作るところだった。
以下、備忘録としてその手順を。
まずは母艦にて、カスタムイメージを作成。
通常のカーネル再構成と同様、 /usr/src/sys/i386/conf/GENERIC をベースに自分用のカーネルの構成をする。
今回は GENERICを NT7001という名前でコピーし、 Bridge/dummynet/Firewall作成用に以下のオプションを追加した上で、 カーネルの軽量化も狙って、 NT7001で使われる rl以外の各種の NICや、 SCSI/RAID関連などの不要なデバイスをざくざくコメントアウトしていく。
options IPFIREWALL options IPFIREWALL_DEFAULT_TO_ACCEPT options DUMMYNET options BRIDGE options HZ=1000
次に、この構成を使って NanoBSDカーネルを作るため、 nanobsd.sh用のカスタムコンフィギュレーションファイルを以下の内容で作成。
NANO_MEDIASIZEに渡している値は、以前 NanoBSDで調べた手持ちの CF用の値。
NANO_MEDIASIZE=`expr 1002258432 / 512` NANO_NAME=nt7001 NANO_KERNEL=NT7001 NANO_SRC=/usr/src CONF_BUILD='\ NO_KLDLOAD=YES\ NO_PAM=YES\ ' COMF_INSTALL='\ NO_ACPI=YES\ NO_BLUETOOTH=YES\ NO_CVS=YES\ NO_FORTRAN=YES\ NO_HTML=YES\ NO_LPR=YES\ NO_MAN=YES\ NO_SENDMAIL=YES\ NO_SHAREDOCS=YES\ NO_EXAMPLES=YES\ NO_INSTALLLIB=YES\ NO_CALENDAR=YES\ NO_MISC=YES\ NO_SHARE=YES\ ' CONF_WORLD='\ NO_BIND=YES\ NO_MODULES=YES\ NO_KERBEROS=YES\ NO_GAMES=YES\ NO_RESCUE=YES\ NO_LOCALES=YES\ NO_SYSCONS=YES\ NO_INFO=YES\ ' cust_allow_ssh_root ### cust_install_files
そして、初回の作成時と同様、
# cd /usr/src/tools/tools/nanobsd # sh nanobsd.sh -c myconf.nano
でイメージ作成。実際のイメージは、 /usr/obj/nanobsd.nt7001/ の下に作成される。
問題は、作成したイメージをどうやって CFにインストールするかだった。
もちろん、初回に作成した時のように、"_.disk.full" を丸ごと ddで CFに書き込んでもいいのだが、 いちいちケースを開けて CFを取り出したりするのは面倒だったし、 何よりその方法だと、すでに動作している環境を丸ごと消してしまうことになる。
すでにユーザを作成したり細々とした設定を入れてあって、 それらを消したくなかったので、 今回は設定を残したままネットワーク越しにアップデートする("_.disk.image"を使う) 方法にチャレンジしてみた。
ふつうに考えると、 すでに OSが動作しているパーティションに別のディスクイメージを重ねて 書くというのは相当無謀な所業だが、実は NanoBSDは、CFを
/dev/ad0s1a /dev/ad0s2a /dev/ad3s
という 3つのパーティションに分けて使っていて、 ad0s1aと、ad0s2aは、まったく同じ大きさのパーティションで、 実際には使うほうだけが read onlyでマウントされる。 (使われない側はマウントもされない。 逆に言えば、CFの半分近い容量は常時遊んでいることになる。)
そして、この、使われていない方のパーティションにイメージを書き込み、 そちらから bootできるようにしてくれるスクリプトが用意されている。 (/usr/src/tools/tools/nanobsd/Files/root/updatep[12])
ただ、これらのスクリプトは、 何も指定せずに nanobsd.shを実行した場合には、インストールされない。
実は動作中の環境はまさにそういう状況だったので、 手動でコピーしてやる必要があった。
また、アップデートの際には、"_.disk.image"を転送しつつ、 これらのスクリプトを母艦側から NanoBSD側の root権限で実行する必要があり、 そのために、SSHで root loginを許可する必要があった。
それらの条件がクリアされていれば、あとは母艦側から、
# cd /usr/obj/nanobsd.nt7001 # cat _.disk.image | ssh nanobsd "sh updatep2"
を実行した後、NanoBSD boxを rebootして、無事にアップデートは完了した。
なお、ad3sは、実際に動作する環境の /etc にコピーされる、 各種の設定の実体が置かれるパーティションで、 こちらも通常はマウントされない。 (ただ、fstabには /cfg に rwでマウントできるような記述がある。)
稼動開始後の設定は、この /cfg/ の下にあるファイルに対して行ってから reboot、というのが一番単純な方法となる。
# 面倒なときは / を rwでマウントし直して、 直接 /cfg/ 配下から /etc/ 配下にコピーしてしまったりもアリかも。