Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
diff files/fbhyve.in @ 474:57f253106ed6
Implement fbhyve, a management system that runs bhyve virtual machines within tmux sessions
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Tue, 27 Aug 2024 21:47:57 +0200 |
| parents | 6ecd16725818 |
| children | 827371176fec |
line wrap: on
line diff
--- a/files/fbhyve.in Mon Aug 26 17:22:26 2024 +0200 +++ b/files/fbhyve.in Tue Aug 27 21:47:57 2024 +0200 @@ -1,7 +1,8 @@ #!/bin/sh +# -*- indent-tabs-mode: nil -*- # PROVIDE: fbhyve -# REQUIRE: LOGIN +# REQUIRE: LOGIN FILESYSTEMS # KEYWORD: shutdown nojail # @@ -9,140 +10,145 @@ # # Add the following lines to /etc/rc.conf to enable bhyve: +# # fbhyve_enable (bool): Set to "NO" by default. -# Set it to "YES" to enable bhyve -# bhyve_profiles (str): Set to "" by default. -# Define your profiles here. -# bhyve_tapdev (str): Set to "tap0" by default. -# Set to the tap(4) device to use. -# bhyve_diskdev (str): Must be set, no default. -# Set to the disk device to use. -# bhyve_ncpu (int): Set to 1 by default. -# Set to the number of CPUs for the VM. -# bhyve_memsize (int): Set to 512 by default. -# Set to the number of MB of memory for the VM. +# Acts as default for all listed VMs. +# Set it to "YES" to enable bhyve. +# fbhyve_list (str): Set to "" by default. +# Define the names of your VMs here. +# fbhyve_tmux_session_prefix (str): All tmux session names will have this +# prefix string. +# fbhyve_configdir (str): Where by default config files for all VMs live. +# Default: $PREFIX/etc/fbhyve +# +# +# fbhyve_<vm>_enable (bool): Allow to enable or disable a specific VM. +# Set to $fbhyve_enable by default. +# fbhyve_<vm>_config (str): The bhyve configuration file to use to. +# The default is $fbhyve_configdir/<vm>.conf +# . /etc/rc.subr name="fbhyve" -rcvar=fbhyve_enable +desc="Manage system bhyve virtual machines" +rcvar="fbhyve_enable" -start_precmd="bhyve_prestart" -status_cmd="bhyve_status" -poll_cmd="bhyve_poll" -stop_cmd="bhyve_stop" -_session=$name -command="/usr/local/bin/tmux" -procname="-sh" +start_precmd="fbhyve_pre_start" +stop_postcmd="fbhyve_post_stop" +status_cmd="fbhyve_status" -[ -z "$bhyve_tapdev" ] && bhyve_tapdev="tap0" -[ -z "$bhyve_diskdev" ] && bhyve_diskdev="none" -[ -z "$bhyve_ncpu" ] && bhyve_ncpu="1" -[ -z "$bhyve_memsize" ] && bhyve_memsize="512" load_rc_config $name -: {fbhyve_enable:="NO"} -: {fbhyve_configdir:="%%PREFIX%%/etc/fbhyve"} +: ${fbhyve_enable:="NO"} +: ${fbhyve_list=} +: ${fbhyve_tmux_session_prefix:="${name}_"} +: ${fbhyve_configdir:="%%FBHYVE_ETCDIR%%"} + + +_fbhyve_vm_exists() { + local _p + for _p in ${fbhyve_list}; do + [ "${_p}" = "$1" ] && return 0; + done + return 1 +} + + +if [ $# -eq 2 ]; then + _vm="$2" + if ! _fbhyve_vm_exists "${_vm}"; then + echo "ERROR: no VM named \`${_vm}' in \`fbhyve_list'" 1>&2 + exit 1 + fi + echo "-- VM: ${_vm} --" + _session="${fbhyve_tmux_session_prefix}${_vm}" + _window="${_session}_console" + eval fbhyve_enable="\${fbhyve_${_vm}_enable:-${fbhyve_enable}}" + eval fbhyve_config="\${fbhyve_${_vm}_config:-\"${fbhyve_configdir}/${_vm}.conf\"}" +else + _ec=0 + _swap=$*; shift; _vmarglist=$* + _vmlist=${_vmarglist:-${fbhyve_list}} + set -- ${_swap} + for _vm in ${_vmlist}; do + "$0" "$1" "${_vm}" + _vmec=$? + if [ ${_vmec} -gt ${_ec} ]; then + _ec=${_vmec} + fi + done + exit ${_ec} +fi + +_rundir="%%FBHYVE_RUNDIR%%" +pidfile="${_rundir}/${_vm}.pid" +procname="bhyve:" # something like bhyve: <vmname> (bhyve) + +required_dirs="${_rundir}" +required_files="${fbhyve_config}" + +command="%%LOCALBASE%%/bin/tmux" + +command_args="new-session -ds ${_session} -n ${_window} \"sh -c 'echo \\\$\\\$ >\\\"${pidfile}\\\"; /usr/sbin/bhyve -k \\\"${fbhyve_config}\\\" \\\"${_vm}\\\"'\"" -if [ -n "$2" ]; then - profile="$2" - _session="${_session}_${profile}" - if [ "x${bhyve_profiles}" != "x" ]; then - eval fbhyve_enable="\${${_session}_enable:-${fbhyve_enable}}" - eval bhyve_tapdev="\${${_session}_tapdev:-${bhyve_tapdev}}" - eval bhyve_diskdev="\${${_session}_diskdev:-${bhyve_diskdev}}" - eval bhyve_ncpu="\${${_session}_ncpu:-${bhyve_ncpu}}" - eval bhyve_memsize="\${${_session}_memsize:-${bhyve_memsize}}" - else - echo "$0: extra argument ignored" - fi -else - if [ "x${bhyve_profiles}" != "x" -a "x$1" != "x" ]; then - for profile in ${bhyve_profiles}; do - eval _enable="\${bhyve_${profile}_enable}" - case "x${_enable:-${fbhyve_enable}}" in - x|x[Nn][Oo]|x[Nn][Oo][Nn][Ee]) - continue - ;; - x[Yy][Ee][Ss]) - ;; - *) - if test -z "$_enable"; then - _var=fbhyve_enable - else - _var=bhyve_"${profile}"_enable - fi - echo "Bad value" \ - "'${_enable:-${fbhyve_enable}}'" \ - "for ${_var}. " \ - "Profile ${profile} skipped." - continue - ;; - esac - echo "===> bhyve profile: ${profile}" - /usr/local/etc/rc.d/bhyve $1 ${profile} - retcode="$?" - if [ "0${retcode}" -ne 0 ]; then - failed="${profile} (${retcode}) ${failed:-}" - else - success="${profile} ${success:-}" - fi - done - exit 0 - fi - profile=$name -fi +fbhyve_status() +{ + local _pid _rc + + _rc=0 + _pid=$(check_pidfile "$pidfile" "$procname") + if [ -n "${_pid}" ]; then + echo "VM ${_vm} is running as pid $_pid." + else + echo "VM ${_vm} is not running." + _rc=1 + fi -pidfile="/var/run/${_session}.pid" + if ${command} has-session -t ${_session} 2>/dev/null; then + echo "tmux session ${_session} exists." + if [ ${_rc} -gt 0 ]; then + _rc=2 + fi + else + echo "tmux session ${_session} does not exist." + if [ ${_rc} -gt 0 ]; then + _rc=2 + fi + fi + return ${_rc} +} -bhyve_prestart() -{ - case ${bhyve_diskdev} in - [Nn][Oo][Nn][Ee] | '') - echo "No ${_session}_diskdev set. Quitting." 1>&2 - return 1; - ;; - esac - if [ ! -c "${bhyve_diskdev}" -a ! -f "${bhyve_diskdev}" ]; then - echo "${bhyve_diskdev} doesn't exist or is not suitable as a diskdev" 1>&2 - return 1; - fi -} - -bhyve_status() -{ - if ${command} has-session -t ${_session} 2>/dev/null; then - echo "${_session} is running." - else - echo "${_session} is not running." - return 1 - fi +fbhyve_pre_start() { + if ! load_kld -m vmm vmm.ko; then + echo "ERROR: Cannot load kernel module \`vmm'" 1>&2 + return 1 + fi + if [ -e "/dev/vmm/${_vm}" ]; then + echo "ERROR: VM \`${_vm}' already created in the VM monitor" 1>&2 + return 1 + fi + if ${command} has-session -t "${_session}" 2>/dev/null; then + echo "ERROR: tmux session \`${_session}' already exists" 1>&2 + return 1 + fi + return 0 } -bhyve_poll() -{ - echo -n "Waiting for session: ${_session}" - while ${command} has-session -t ${_session} 2>/dev/null; do - sleep 1 - done - echo + +fbhyve_post_stop() { + if [ -e "/dev/vmm/${_vm}" ]; then + /usr/sbin/bhyvectl --vm="${_vm}" --destroy + fi + if ${command} has-session -t "${_session}" 2>/dev/null; then + ${command} kill-session -t "${_session}" + fi + rm -f "${pidfile}" + return 0 } -bhyve_stop() -{ - if ${command} has-session -t ${_session} 2>/dev/null; then - echo "Stopping ${_session}." - ${command} kill-session -t ${_session} - while ${command} has-session -t ${_session} 2>/dev/null; do - sleep 1 - done - fi - rm -f ${pidfile} -} - -command_args="new-session -ds ${_session} \"sh -c 'echo \\\$PPID >${pidfile}; while true; do /usr/sbin/bhyvectl --vm=${_session} --destroy; /usr/sbin/bhyveload -m ${bhyve_memsize} -d ${bhyve_diskdev} ${_session} && /usr/sbin/bhyve -c ${bhyve_ncpu} -m ${bhyve_memsize} -AI -H -P -g 0 -s 0:0,hostbridge -s 1:0,virtio-net,${bhyve_tapdev} -s 2:0,virtio-blk,${bhyve_diskdev} -s 31,lpc -l com1,stdio ${_session} || break; done'\"" run_rc_command "$1"
