BHyVeを安直に動かしたいという目的で作った、「BHyVeお手軽スクリプト」を公開します。
基本ZFS用ですが、ufsでも使えます。事前にvmm.koをロードする必要があります。
このファイルを適当な名前(例えば bhyve-util等)で保存して、システム名-コマンド名でシンボリックリンクを貼ります。
$ ln -s bhyve-util freebsd0-boot
$ ln -s bhyve-util freebsd0-boottty
$ ln -s bhyve-util freebsd0-clean
$ ln -s bhyve-util freebsd0-console
$ ln -s bhyve-util freebsd0-install
$ ln -s bhyve-util freebsd0-resources
$ ln -s bhyve-util freebsd0-shutdown
内部の __config_system 関数内の設定を必要に応じて修正します。1回目はfreebsd0-installを実行し、インストール後に freebsd0-boot を実行すれば動きます。
とりあえず、FreeBSD アドベントカレンダーを埋めてる目的で、今日はここまで(かなりヒドイ)。
2018-12-20 追記
更新版を公開しました。「続 BHyVe お手軽スクリプト 」を見てください。
#!/bin/sh
#
# BHyVe での Grubを使うOSのインストール/起動スクリプト
# プログラム名
# システム名-install bhyveへのインストール
# システム名-boot インストール済みシステムの起動
# システム名-boottty consoleをttyで起動 (*-boot -t でも同じ)
# システム名-console null-modem経由でコンソールへ接続
# システム名-resources リソースの表示
# システム名-shutodnw VMMのシャットダウン
# システム名-clean VMMのクリア
#
export PATH=/usr/local/bin:/usr/local/sbin:/bin:/usr/bin:/sbin:/usr/sbin
cpu=1 # VMのデフォルトのCPU数
mem=256M # VMのデフォルトのメモリサイズ
bridge=bridge0 # デフォルトのbridge if
zvol_pre=zroot/vm # VM用ZFS Volumeのprefix
iso_prefix=/home/archives/ISO # ISO image のあるPathのprefix
zvol_opt='-o volmode=dev -o volblocksize=4k' # ZFS Volumeのプロパティ
do_daemon=daemon # daemon コマンド
# VMのリソース割り当て
#
# 新たなVMを増やす場合
# case文のエントリーを増やす
# _id に新規の番号を割り当てる
# 適当なISOイメージを割り当てる
#
# con: consoleが接続されるヌルモデムのデバイス名 ex. /dev/nmdm0A
# tap: tap IFの名前 ex tap0
# tapX と /dev/nmdmXA の Xの番号は一致し、_id に設定した値を使う
# zvol: VM用 zfs volume
# システム名とZFSのvolume名は同じ名前であることを前提としている
# hd0: システムディスク 通常 /dev/zvol/${zvol_pre}/${system}
# cd0: インストール用のISOイメージ
# freebsd: ターゲットOSがfreebsdならばYES
# grub_inst_cmd: (optional) grub-bhyveでinstallに必要なコマンド列
# grub_boot_cmd: (optional) grub-bhyveでbootに必要なコマンド列
#
__config_system () {
local _id _iso _ver _kern _ramfs _root
case ${system} in
ubuntu0)
_id=0
_iso=Ubuntu/ubuntu-16.04-server-amd64.iso
;;
debian0)
_id=1
_iso=Debian/debian-8.4.0-amd64-netinst.iso
;;
centos0)
_id=2
_iso=CentOS/CentOS-7-x86_64-Minimal-1511.iso
_ver="3.10.0-327" # install時のCentOS 7のオリジナル
_ver="3.10.0-327.18.2" # update によって適宜更新する
_ver="3.10.0-327.22.2" # update によって適宜更新する
_ver="3.10.0-327.28.2" # update によって適宜更新する
_ver="3.10.0-327.28.3" # update によって適宜更新する
_root=/dev/mapper/centos-root
_kern="(hd0,msdos1)/vmlinuz-${_ver}.el7.x86_64"
_ramfs="(hd0,msdos1)/initramfs-${_ver}.el7.x86_64.img"
grub_inst_cmd="linux (cd0)/isolinux/vmlinuz; initrd (cd0)/isolinux/initrd.img"
grub_boot_cmd="linux ${_kern} root=${_root}; initrd ${_ramfs}"
;;
openbsd0)
_id=3
_iso=OpenBSD/install59.iso
_ver=5.9
grub_inst_cmd="kopenbsd -h com0 (cd0)/${_ver}/amd64/bsd.rd"
grub_boot_cmd="kopenbsd -h com0 -r sd0a (hd0,openbsd1)/bsd"
;;
netbsd0)
_id=4
_iso=NetBSD/NetBSD-7.0.1-amd64.iso
grub_inst_cmd="knetbsd -h -r cd0a (cd0)/netbsd"
grub_boot_cmd="knetbsd -h -r /dev/rld0a (hd0,netbsd1)/netbsd"
;;
freebsd0)
_id=5
_iso=FreeBSD/FreeBSD-10.3-RELEASE-amd64-disc1.iso
freebsd=YES
;;
fbsdzfs0)
_id=6
_iso=FreeBSD/FreeBSD-10.3-RELEASE-amd64-disc1.iso
freebsd=YES
mem=512M
;;
ubuntubsd0)
_id=7
_iso=ubuntuBSD/ubuntuBSD-15.10~BETA5-amd64.iso
;;
*)
echo "*** ${0##*/} is bad name" 1>&2 ; exit 1
;;
esac
tap=tap${_id}
con=/dev/nmdm${_id}A
zvol=${zvol:-${zvol_pre}/${system}}
hd0=${hd0:-/dev/zvol/${zvol}}
cd0=${cd0:-${iso_prefix}/${_iso}}
}
__check_running () {
pgrep -qf "bhyve: ${system}"
return $?
}
# Bhyve 用ZFS volumeの作成 (HOGE-ressouces 時)
__make_zvol () {
if [ -e "${hd0}" ]; then
echo "*** ${hd0} already exist" 1>&2
else
sudo zfs create ${s_flag} -V ${V_size} ${zvol_opt} ${zvol} || exit
fi
}
# Bhyve 用tap ifの作成
__make_tap () {
if ifconfig "${tap}" >/dev/null 2>&1; then
echo "*** ${tap} already exist" 1>&2
else
sudo ifconfig ${tap} create
sudo ifconfig ${bridge} addm ${tap}
fi
}
# ディスクイメージがあるかどうかの確認
__check_resouces() {
local _badconfig
if [ ! -e "${hd0}" ]; then
echo "*** ${hd0} not found." 1>&2
_badconfig=YES
fi
if [ x"${install}" = xYES -a ! -e "${cd0}" ]; then
echo "*** ${cd0} not found." 1>&2
_badconfig=YES
fi
if [ x"${_badconfig}" = x"YES" ]; then
exit 1 # 問題があれば終了
fi
}
__connect_console() { # nmdmデバイス経由でコンソールへ接続する
local nmdm
nmdm=`echo ${con} | tr 'A' 'B'`
exec sudo cu -l ${nmdm}
}
__print_resources () {
if [ "x${V_size}" != x ]; then
__make_zvol
fi
echo tap=${tap}
echo con=${con}
echo zvol=${zvol}
echo hd0=${hd0}
echo cd0=${cd0}
}
__grub_install () {
local _st
cat <<- EOT > ${map}
(hd0) ${hd0}
(cd0) ${cd0}
EOT
if [ x${grub_inst_cmd} = x ]; then
sudo grub-bhyve -m ${map} -r cd0 -M ${mem} ${system}
else
sudo grub-bhyve -m ${map} -r cd0 -M ${mem} ${system} <<- EOT
${grub_inst_cmd}
boot
EOT
fi
_st=$?
rm -f ${map}
# インストーラの起動
[ ${_st} -eq 0 ] && exec sudo bhyve -A -H -P \
-c ${cpu} \
-m ${mem} \
-l com1,stdio \
-s 0:0,hostbridge \
-s 1:0,lpc \
-s 2:0,virtio-net,${tap} \
-s 3:0,virtio-blk,${hd0} \
-s 4:0,ahci-cd,${cd0} \
${system}
}
__clean_vm () {
if pgrep -fq "bhyve: ${system}"
then
echo "*** ${system} is running" 1>&2
exit 2
fi
if [ -e /dev/vmm/${system} ] ;
then
sudo bhyvectl --destroy --vm=${system} # VMのクリア
fi
if ifconfig ${tap} >/dev/null 2>&1
then
sudo ifconfig ${bridge} deletem ${tap}
sudo ifconfig ${tap} destroy
fi
}
__shutdown_vm () {
local _pid _i
if ! _pid=$(pgrep -f "bhyve: ${system}")
then
echo "*** ${system} is not running" 1>&2
exit 2
fi
sudo kill ${_pid}
test ${q_flag} || echo -n "Waiting for shutdown ${system} " 1>&2
_i=0
while pgrep -qf "bhyve: ${system}"
do
_i=$((_i + 1))
if [ ${_i} -ge 150 ] # shutdownを2分半までは待つ
then
echo "**** ${system}: can not shutdown!" 1>&2
exit 2
fi
sleep 1
test ${q_flag} || echo -n '.' 1>&2
done
__clean_vm
test ${q_flag} || echo " Done." 1>&2
}
__grub_boot () {
local _st
# boot用のmapファイルの作成
cat <<- EOT > ${map}
(hd0) ${hd0}
EOT
[ ! -z "${hd1}" ] && hd2nd="-s 4:0,virtio-blk,${hd1}"
# Boot用の Grubの起動
#
if [ x"${grub_boot_cmd}" = x -o x"${p_flag}" = xYES ]; then
sudo grub-bhyve -m ${map} -r hd0,msdos1 -M ${mem} ${system}
else
sudo grub-bhyve -m ${map} -r hd0,msdos1 -M ${mem} ${system} <<- EOT
${grub_boot_cmd}
boot
EOT
fi
_st=$?
rm -f ${map}
# bhyveの起動
[ ${_st} -eq 0 ] && exec sudo ${do_daemon} bhyve -A -H -P \
-c ${cpu} \
-m ${mem} \
-l com1,${con} \
-s 0:0,hostbridge \
-s 1:0,lpc \
-s 2:0,virtio-net,${tap} \
-s 3:0,virtio-blk,${hd0} ${hd2nd} \
${system}
}
__freebsd_install () {
sudo bhyveload -c stdio -m ${mem} -d ${cd0} ${system} &&
sudo bhyve -H -A -P \
-c ${cpu} \
-m ${mem} \
-l com1,stdio \
-s 0:0,hostbridge \
-s 1:0,lpc \
-s 2:0,virtio-net,${tap} \
-s 3:0,virtio-blk,${hd0} ${hd2nd} \
-s 31:0,ahci-cd,${cd0} \
${system}
}
__freebsd_boot () {
[ ! -z "${hd1}" ] && hd2nd="-s 4:0,virtio-blk,${hd1}"
sudo bhyveload -c stdio -m ${mem} -d ${hd0} ${system} &&
exec sudo ${do_daemon} bhyve -H -A -P \
-c ${cpu} \
-m ${mem} \
-l com1,${con} \
-s 0:0,hostbridge \
-s 1:0,lpc \
-s 2:0,virtio-net,${tap} \
-s 3:0,virtio-blk,${hd0} ${hd2nd} \
${system}
}
# ----- ここからメイン -----
prog=${0##*/}
system=${prog%-*} # "XXX-hogehoge"の"XXX"をシステム名
cmd=${prog##*-} # "hogehoge"をコマンド名
__config_system
# -t オプションがあればサーバーをバックグラウンド処理にしない
# -c cpu数
# -m メモリサイズ
# -V size 指定サイズのvolumeの作成 (*-resources のみ)
# -I tap の作成 (*-resources のみ)
#
while getopts 'qpstc:m:IV:' cmd_arg; do
case "${cmd_arg}" in
t) con=stdio ; unset do_daemon ;;
c) cpu=${OPTARG} ;;
m) mem=${OPTARG} ;;
I) I_flag=YES ;;
s) s_flag=-s ;;
p) p_flag=YES ;;
q) q_flag=YES ;;
V) V_size=${OPTARG} ;;
*) echo "Usage: ${0##*/} [ -t ]" 1>&2; exit 2;;
esac
done
shift $((OPTIND - 1))
# コマンドの判断
#
case ${cmd} in
clean) __clean_vm ; exit ;;
resources) __print_resources ; exit ;;
boot) ;;
boottty) con=stdio ; unset do_daemon ;;
install) install=YES ;;
console) __connect_console ;;
shutdown) __shutdown_vm ; exit ;;
*) echo "*** ${cmd}: Unknown Commmand" 1>&2 ; exit 2 ;;
esac
__check_resouces
__clean_vm
__make_tap
cd /tmp # ワーキングディレクトリを /tmp に変更
if [ x${freebsd} = xYES ]; then
if [ x${install} = xYES ]; then
__freebsd_install
else
__freebsd_boot
fi
else
map=`mktemp /tmp/_bhyve-map-${system}-XXXXXX` # grub-bhyve用mapファイル
if [ x${install} = xYES ]; then
__grub_install
else
__grub_boot
fi
fi