Add support for both NAT and RAW network interfaces in virtual machine.
This is used so metallb can announce public ip addresses.
This commit is contained in:
parent
bb41cb6a96
commit
f3980dc821
@ -21,17 +21,22 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||||||
# doas bhyve_netgraph_bridge start poudriere zdata/vm/poudriere /vm/poudriere /vm/iso/FreeBSD-13.2-RELEASE-amd64-bootonly.iso
|
# doas bhyve_netgraph_bridge start poudriere zdata/vm/poudriere /vm/poudriere /vm/iso/FreeBSD-13.2-RELEASE-amd64-bootonly.iso
|
||||||
# doas bhyve_netgraph_bridge start poudriere zdata/vm/poudriere /vm/poudriere
|
# doas bhyve_netgraph_bridge start poudriere zdata/vm/poudriere /vm/poudriere
|
||||||
|
|
||||||
|
: ${VERBOSE:="NO"} # or YES
|
||||||
: ${CPU_CORES:="1"}
|
: ${CPU_CORES:="1"}
|
||||||
: ${MEMORY:="1G"}
|
: ${MEMORY:="1G"}
|
||||||
: ${NETWORK:="NAT"} # or RAW
|
: ${NETWORK:="NAT"} # or RAW or BOTH
|
||||||
: ${IP_RANGE:="10.215.1.1/24"} # Ignored for RAW networks
|
: ${IP_RANGE:="10.215.1.1/24"} # Ignored for RAW networks
|
||||||
: ${INTERFACE_NAME:="jail_nat"} # or the external interface like lagg0 for RAW networks
|
: ${INTERFACE_NAME:="jail_nat"} # or the external interface like lagg0 for RAW networks
|
||||||
: ${BRIDGE_NAME:="bridge_$INTERFACE_NAME"} # or bridge_raw for RAW networks
|
: ${BRIDGE_NAME:="bridge_$INTERFACE_NAME"} # or bridge_raw for RAW networks
|
||||||
: ${VNC_ENABLE:="NO"}
|
: ${VNC_ENABLE:="NO"}
|
||||||
: ${VNC_LISTEN:="127.0.0.1:5900"}
|
: ${VNC_LISTEN:="127.0.0.1:5900"}
|
||||||
|
|
||||||
|
if [ "$VERBOSE" = "YES" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
function main {
|
function main {
|
||||||
cmd="$1"
|
local cmd="$1"
|
||||||
shift 1
|
shift 1
|
||||||
if [ "$cmd" = "create-disk" ]; then
|
if [ "$cmd" = "create-disk" ]; then
|
||||||
create_disk "${@}"
|
create_disk "${@}"
|
||||||
@ -50,9 +55,9 @@ function die {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function create_disk {
|
function create_disk {
|
||||||
zfs_path="$1"
|
local zfs_path="$1"
|
||||||
mount_path="$2"
|
local mount_path="$2"
|
||||||
gigabytes="$3"
|
local gigabytes="$3"
|
||||||
zfs create -o "mountpoint=$mount_path" "$zfs_path"
|
zfs create -o "mountpoint=$mount_path" "$zfs_path"
|
||||||
cp /usr/local/share/edk2-bhyve/BHYVE_UEFI_VARS.fd "${mount_path}/"
|
cp /usr/local/share/edk2-bhyve/BHYVE_UEFI_VARS.fd "${mount_path}/"
|
||||||
tee "${mount_path}/settings" <<EOF
|
tee "${mount_path}/settings" <<EOF
|
||||||
@ -67,30 +72,42 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
function start_vm {
|
function start_vm {
|
||||||
name="$1"
|
local name="$1"
|
||||||
zfs_path="$2"
|
local zfs_path="$2"
|
||||||
mount_path="$3"
|
local mount_path="$3"
|
||||||
mount_cd="${4:-}"
|
local mount_cd="${4:-}"
|
||||||
|
|
||||||
if [ -e "${mount_path}/settings" ]; then
|
if [ -e "${mount_path}/settings" ]; then
|
||||||
source "${mount_path}/settings"
|
source "${mount_path}/settings"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
host_interface_name="$INTERFACE_NAME" # for raw, external interface
|
local host_interface_name="$INTERFACE_NAME" # for raw, external interface
|
||||||
bridge_name="$BRIDGE_NAME"
|
local bridge_name="$BRIDGE_NAME"
|
||||||
ip_range="$IP_RANGE" # for raw this value does not matter
|
local ip_range="$IP_RANGE" # for raw this value does not matter
|
||||||
|
|
||||||
mac_address=$(calculate_mac_address "$name")
|
local mac_address=$(calculate_mac_address "$name")
|
||||||
|
|
||||||
|
local additional_args=()
|
||||||
|
|
||||||
if [ "$NETWORK" = "NAT" ]; then
|
if [ "$NETWORK" = "NAT" ]; then
|
||||||
assert_bridge "$host_interface_name" "$bridge_name" "$ip_range"
|
assert_bridge "$host_interface_name" "$bridge_name" "$ip_range"
|
||||||
|
local bridge_link_name=$(detect_available_link "${bridge_name}")
|
||||||
|
additional_args+=("-s" "2:0,virtio-net,netgraph,path=${bridge_name}:,peerhook=${bridge_link_name},mac=${mac_address}")
|
||||||
elif [ "$NETWORK" = "RAW" ]; then
|
elif [ "$NETWORK" = "RAW" ]; then
|
||||||
assert_raw "$host_interface_name" "$bridge_name"
|
assert_raw "$host_interface_name" "$bridge_name"
|
||||||
|
local bridge_link_name=$(detect_available_link "${bridge_name}")
|
||||||
|
additional_args+=("-s" "2:0,virtio-net,netgraph,path=${bridge_name}:,peerhook=${bridge_link_name},mac=${mac_address}")
|
||||||
|
elif [ "$NETWORK" = "BOTH" ]; then
|
||||||
|
assert_bridge "jail_nat" "$bridge_name" "$ip_range"
|
||||||
|
assert_raw "$host_interface_name" "bridge_raw"
|
||||||
|
local bridge_link_name=$(detect_available_link "${bridge_name}")
|
||||||
|
local raw_bridge_link_name=$(detect_available_link "bridge_raw")
|
||||||
|
local raw_mac_address=$(calculate_mac_address "${name}_raw")
|
||||||
|
additional_args+=("-s" "2:0,virtio-net,netgraph,path=${bridge_name}:,peerhook=${bridge_link_name},mac=${mac_address}")
|
||||||
|
additional_args+=("-s" "3:0,virtio-net,netgraph,path=bridge_raw:,peerhook=${raw_bridge_link_name},mac=${raw_mac_address}")
|
||||||
else
|
else
|
||||||
die 1 "Unrecognized NETWORK type $NETWORK"
|
die 1 "Unrecognized NETWORK type $NETWORK"
|
||||||
fi
|
fi
|
||||||
bridge_link_name=$(detect_available_link "${bridge_name}")
|
|
||||||
|
|
||||||
|
|
||||||
# -H release the CPU when guest issues HLT instruction. Otherwise 100% of core will be consumed.
|
# -H release the CPU when guest issues HLT instruction. Otherwise 100% of core will be consumed.
|
||||||
@ -99,7 +116,6 @@ function start_vm {
|
|||||||
# -s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080 \
|
# -s 29,fbuf,tcp=0.0.0.0:5900,w=1920,h=1080 \
|
||||||
|
|
||||||
# TODO: Look into using nmdm instead of stdio for serial console
|
# TODO: Look into using nmdm instead of stdio for serial console
|
||||||
additional_args=()
|
|
||||||
if [ -n "$mount_cd" ]; then
|
if [ -n "$mount_cd" ]; then
|
||||||
additional_args+=("-s" "3,ahci-cd,$mount_cd")
|
additional_args+=("-s" "3,ahci-cd,$mount_cd")
|
||||||
fi
|
fi
|
||||||
@ -116,13 +132,12 @@ function start_vm {
|
|||||||
-H \
|
-H \
|
||||||
-s 0,hostbridge \
|
-s 0,hostbridge \
|
||||||
-s "4,nvme,/dev/zvol/${zfs_path}/disk0" \
|
-s "4,nvme,/dev/zvol/${zfs_path}/disk0" \
|
||||||
-s "2:0,virtio-net,netgraph,path=${bridge_name}:,peerhook=${bridge_link_name},mac=${mac_address}" \
|
|
||||||
-s 30,xhci,tablet \
|
-s 30,xhci,tablet \
|
||||||
-s 31,lpc -l com1,stdio \
|
-s 31,lpc -l com1,stdio \
|
||||||
-l "bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd,${mount_path}/BHYVE_UEFI_VARS.fd" \
|
-l "bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd,${mount_path}/BHYVE_UEFI_VARS.fd" \
|
||||||
"${additional_args[@]}" \
|
"${additional_args[@]}" \
|
||||||
"$name"
|
"$name"
|
||||||
exit_code=$?
|
local exit_code=$?
|
||||||
set -e
|
set -e
|
||||||
set +x
|
set +x
|
||||||
if [ $exit_code -eq 0 ]; then
|
if [ $exit_code -eq 0 ]; then
|
||||||
@ -147,10 +162,10 @@ function start_vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function detect_available_link {
|
function detect_available_link {
|
||||||
bridge_name="$1"
|
local bridge_name="$1"
|
||||||
linknum=1
|
local linknum=1
|
||||||
while true; do
|
while true; do
|
||||||
link_name="link${linknum}"
|
local link_name="link${linknum}"
|
||||||
if ! ng_exists "${bridge_name}:${link_name}"; then
|
if ! ng_exists "${bridge_name}:${link_name}"; then
|
||||||
echo "$link_name"
|
echo "$link_name"
|
||||||
return
|
return
|
||||||
@ -164,9 +179,9 @@ function detect_available_link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function assert_bridge {
|
function assert_bridge {
|
||||||
host_interface_name="$1"
|
local host_interface_name="$1"
|
||||||
bridge_name="$2"
|
local bridge_name="$2"
|
||||||
ip_range="$3"
|
local ip_range="$3"
|
||||||
|
|
||||||
if ! ng_exists "${bridge_name}:"; then
|
if ! ng_exists "${bridge_name}:"; then
|
||||||
ngctl -d -f - <<EOF
|
ngctl -d -f - <<EOF
|
||||||
@ -182,13 +197,13 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
function assert_raw {
|
function assert_raw {
|
||||||
extif="$1"
|
local extif="$1"
|
||||||
bridge_name="$2"
|
local bridge_name="$2"
|
||||||
|
|
||||||
kldload -n ng_bridge ng_eiface ng_ether
|
kldload -n ng_bridge ng_eiface ng_ether
|
||||||
|
|
||||||
if ! ng_exists "${bridge_name}:"; then
|
if ! ng_exists "${bridge_name}:"; then
|
||||||
ngctl -d -f - <<EOF
|
ngctlcat <<EOF
|
||||||
# Create a bridge.
|
# Create a bridge.
|
||||||
mkpeer $extif: bridge lower link0
|
mkpeer $extif: bridge lower link0
|
||||||
# Assign a name to the bridge.
|
# Assign a name to the bridge.
|
||||||
@ -210,19 +225,27 @@ function ng_exists {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function calculate_mac_address {
|
function calculate_mac_address {
|
||||||
name="$1"
|
local name="$1"
|
||||||
source=$(md5 -r -s "$name" | awk '{print $1}')
|
local source=$(md5 -r -s "$name" | awk '{print $1}')
|
||||||
echo "06:${source:0:2}:${source:2:2}:${source:4:2}:${source:6:2}:${source:8:2}"
|
echo "06:${source:0:2}:${source:2:2}:${source:4:2}:${source:6:2}:${source:8:2}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function find_available_port {
|
function find_available_port {
|
||||||
start_port="$1"
|
local start_port="$1"
|
||||||
port="$start_port"
|
local port="$start_port"
|
||||||
while true; do
|
while true; do
|
||||||
sockstat -P tcp -p 443
|
sockstat -P tcp -p 443
|
||||||
port=$((port + 1))
|
port=$((port + 1))
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ngctlcat {
|
||||||
|
if [ "$VERBOSE" = "YES" ]; then
|
||||||
|
tee /dev/tty | ngctl -d -f -
|
||||||
|
else
|
||||||
|
ngctl -d -f -
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
main "${@}"
|
main "${@}"
|
||||||
|
Loading…
Reference in New Issue
Block a user