Hello everyone!
I'm creating an rc.d script to start a virtual machine at reboot, which is accessible by remote-connection.
The problem is, I'm not able to let the machine start in background, so that I can still continue working with the shell of the FreeBSD PC (which is, to be precise, a TwinCat/BSD-IPC).
The virtual machine (OS: Windows 10) that should be started, has already been created previously and is also reachable via the remote-connection.
Has anybody an idea what the problem could be?
By the way, the script is saved in /usr/local/bin and is linked to the /usr/local/etc/rc.d directory, just in case this is relevant.
This is the script I created:
Would be great if anyone out there could help me further.
Thanks in advance!
I'm creating an rc.d script to start a virtual machine at reboot, which is accessible by remote-connection.
The problem is, I'm not able to let the machine start in background, so that I can still continue working with the shell of the FreeBSD PC (which is, to be precise, a TwinCat/BSD-IPC).
The virtual machine (OS: Windows 10) that should be started, has already been created previously and is also reachable via the remote-connection.
Has anybody an idea what the problem could be?
By the way, the script is saved in /usr/local/bin and is linked to the /usr/local/etc/rc.d directory, just in case this is relevant.
This is the script I created:
Code:
#!/bin/sh
# SPDX-License-Identifier: 0BSD
# Copyright (C) 2019 - 2022 Beckhoff Automation GmbH & Co. KG
# PROVIDE: ${name}
# REQUIRE: DAEMON NETWORKING dmesg
# BEFORE: LOGIN TcSystemService
# KEYWORD: nojail shutdown
. /etc/rc.subr
name="samplevm"
rcvar="${name}_enable"
command="/usr/local/bin/${name}"
export PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
start_cmd="${command} start > /dev/null 2>&1 &"
stop_cmd="${command} stop > /dev/null 2>&1 &"
status_cmd="${command} status"
set -e
set -u
usage() {
cat >&2 << EOF
USAGE: ${0##*/} [COMMAND]
Control the virtual machine environment named '${name}'
COMMANDS:
start Start the VM
stop Shutdown the running VM
help Print this help message
EXAMPLES
# run the virual machine
${0##*/} start
# shutdown the virtual machine
${0##*/} stop
EOF
}
# Cleanup any resources used by the VM after shutdown
cleanup() {
# do not trap during cleanup procedure
trap '' EXIT
set +e
set +u
pfctl -a "bhf/bhyve/${name}" -f /dev/null > /dev/null 2>&1
if test -e "${temp_firewall_rules}"; then
rm "${temp_firewall_rules}"
fi
}
prepare_host() {
# Ensure that kernel modul vmm.ko is loaded
kldload -n vmm.ko
# accept incoming VNC and remote connections
service pf stop
temp_firewall_rules="/etc/pf.conf.d/${name}"
printf "pass in quick proto tcp to port %s\n" "${samplevm_vncport}" > "${temp_firewall_rules}"
pfctl -a bhf/bhyve/"${name}" -f "${temp_firewall_rules}"
}
run_vm() {
trap 'cleanup' EXIT
prepare_host
while true; do
# destroy former VM instance to ensure we start
# with a clean VM configuration
if test -e /dev/vmm/${name}; then
bhyvectl --vm="${name}" --destroy
echo "current VM was beeing destroyed in order to restart"
else
echo "VM starting..."
fi
#check if mountpoint exists
if !(zfs list -H -o mountpoint | grep -q ${samplevm_path}); then
zfs create -p -o mountpoint=${samplevm_path} zroot${samplevm_path}
fi
#create a disk for the virtual machine, size of 40GB is necessarily needed for Windows 10 installation
if (zfs list | grep -F -q "zroot${samplevm_path}/disk0"); then
echo "existing disk is used"
#check if size is ok
if zfs get volsize zroot${samplevm_path}/disk0 | grep -q "50G"; then
#size is ok
else
zfs set volsize=50G zroot${samplevm_path}/disk0
fi
else
zfs create -V 50G zroot${samplevm_path}/disk0
fi
# create an interface for the virtual machine
if ifconfig | grep -q tap0; then
# use existing
else
ifconfig tap create
sysrc cloned_interfaces+="tap0"
fi
# create a bridge if not already existing
if ifconfig | grep -q bridge0; then
#use existing
if -q "ifconfig_bridge0" /etc/rc.conf; then
#persistant configuration finished
else
sysrc ifconfig_bridge0="addm igb1 addm tap0"
fi
else
ifconfig bridge create
sysrc cloned_interfaces+="bridge0"
sysrc ifconfig_bridge0="addm igb1 addm tap0"
fi
# set ppt driver (PCI PassThrough)
if (pciconf -l | grep -F -q "igb2@pci0:3:0:0:"); then
devctl set driver -f pci0:3:0:0 ppt
elif (pciconf -l | grep -q "ppt0@pci0:3:0:0:"); then
echo "pass through driver is set to igb2"
# ppt was already set to igb2
else
echo "an error occured, please check the pass-through configuration with pciconf -l and change the settings"
fi
if grep -F -q "3/0/0" /boot/loader.conf; then
#already persistantly safed
else
echo "pptdevs="3/0/0"" >> /boot/loader.conf
fi
if test -e ${samplevm_path}/BHYVE_BHF_UEFI_VARS.fd; then
# VARS-File already copied in the vm-path
elif !(test -e ${samplevm_path}/BHYVE_BHF_UEFI_VARS.fd); then
if test -e ${samplevm_path}/; then
cp /usr/local/share/uefi-firmware/BHYVE_BHF_UEFI_VARS.fd ${samplevm_path}/;
else
mkdir -m a+rwx ${samplevm_path}
cp /usr/local/share/uefi-firmware/BHYVE_BHF_UEFI_VARS.fd ${samplevm_path}/;
fi
fi
_bhyve_rc=0
bhyve \
-c sockets=1,cores=1,threads=1 \
-m 2G \
-s 0,hostbridge \
-s 10,nvme,/dev/zvol/zroot/vms/samplevm/disk0 \
-s 20,virtio-net,tap0 \
-s 21,passthru,3/0/0 \
-s 30,xhci,tablet \
-s 31,lpc \
-l com1,stdio \
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd,${samplevm_path}/BHYVE_BHF_UEFI_VARS.fd \
-H -P -A -S -w \
"${name}" || _bhyve_rc=$?
if test "${_bhyve_rc}" -ne 0; then
break
fi
done
}
shutdown_vm() {
# do not trap on exit during shutdown command
trap '' EXIT
set +e
set +u
kill "${_pid}"
}
get_bhyve_pid() {
printf "%s" "$(pgrep -f "bhyve: ${name}")"
}
# Execution of virtual machines requires root previleges
if test "$(id -u)" -ne 0; then
printf "%s must be run as root\n" "${0##*/}"
exit 1
fi
# Default values for VM configuration
: ${samplevm_enable:="NO"}
: ${samplevm_vncport:="5900"}
: ${samplevm_path:="/vms/samplevm"}
readonly _cmd="${1?Error: No COMMAND specified$(usage)}"
_pid="$(get_bhyve_pid)"
case "${_cmd}" in
start)
if test -z "${_pid:+x}"; then
run_vm
else
printf "%s is already running with pid: %s\n" "${name}" "${_pid}"
exit 1
fi
;;
stop)
if ! test -z "${_pid:+x}"; then
shutdown_vm
fi
;;
status)
if ! test -z "${_pid:+x}"; then
printf "'%s' is running with pid: %s\n" "${name}" "${_pid}"
else
printf "'%s' is not running.\n" "${name}"
fi
;;
Thanks in advance!