fix(host): bring up VMware host stack at boot via native systemd units
Build VMs stopped starting after a reboot into a new kernel: vmmon/vmnet
were left unloaded and vmnet1/vmnet8 (DHCP/NAT) never came up, so
vmware-vmx died (status=237/KEYRING) and clones got no IP. Root cause:
the LSB->systemd sysv-generated vmware.service intermittently fails to
generate at early boot ("systemd-sysv-generator: Cannot find unit
vmware.service"), and the existing module-rebuild guard only builds the
modules -- it never loads them or starts vmnet networking.
Add a native vmware-host.service that runs `/etc/init.d/vmware start`
(loads vmmon/vmci + brings up vmnet), ordered after the rebuild guard,
and mask the flaky sysv vmware.service so the native unit is the sole
owner. Provisioned by scripts/install-vmware-host-services.sh and wired
into setup-host-linux.sh (new step 8/9). VMware ships no native unit and
no kernel postinst hook, so this native wrapper around VMware's own
tools is the reliable boot path.
Verified: linked clone boots and gets a vmnet8 DHCP IP.
This commit is contained in:
Executable
+90
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env bash
|
||||
# install-vmware-host-services.sh — install the native systemd units that bring
|
||||
# up the VMware Workstation host stack at boot on the Linux CI host.
|
||||
#
|
||||
# Why this exists: VMware Workstation on Linux ships NO native systemd unit,
|
||||
# does NOT register vmmon/vmnet with DKMS, and installs NO kernel postinst hook.
|
||||
# Two failure modes follow, both of which stop build VMs from starting:
|
||||
# 1. After a kernel upgrade the vmmon/vmnet .ko are unbuilt until
|
||||
# vmware-modconfig runs (vmrun start => "Error: The operation was
|
||||
# canceled").
|
||||
# 2. The LSB-generated sysv `vmware.service` has proven unreliable to generate
|
||||
# at early boot ("systemd-sysv-generator: Cannot find unit vmware.service"),
|
||||
# so vmmon stays unloaded and vmnet1/vmnet8 (DHCP/NAT) never come up.
|
||||
#
|
||||
# This installs two native systemd units built on VMware's own tools:
|
||||
# - vmware-modules-rebuild.service : rebuilds vmmon/vmnet via vmware-modconfig
|
||||
# if the .ko for the running kernel is missing (build-if-missing guard).
|
||||
# - vmware-host.service : runs `/etc/init.d/vmware start` to load
|
||||
# the modules and bring up vmnet networking; ordered After the guard.
|
||||
# The flaky sysv `vmware.service` is masked so vmware-host.service is the sole
|
||||
# owner of the host stack.
|
||||
#
|
||||
# Usage:
|
||||
# sudo ./scripts/install-vmware-host-services.sh # install + enable + start
|
||||
# sudo ./scripts/install-vmware-host-services.sh --uninstall
|
||||
#
|
||||
# Idempotent: re-running overwrites the units in place and re-enables them.
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
SRC="$REPO_DIR/deploy/systemd"
|
||||
ACTION="install"
|
||||
|
||||
log() { printf '[install-vmware-host-services] %s\n' "$*"; }
|
||||
warn() { printf '[install-vmware-host-services] WARN: %s\n' "$*" >&2; }
|
||||
die() { printf '[install-vmware-host-services] ERROR: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--uninstall) ACTION="uninstall"; shift ;;
|
||||
-h|--help) sed -n '2,29p' "$0"; exit 0 ;;
|
||||
*) die "unknown argument: $1 (use --uninstall)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "run as root: sudo bash $0"
|
||||
|
||||
if [ "$ACTION" = "uninstall" ]; then
|
||||
systemctl disable --now vmware-host.service 2>/dev/null || true
|
||||
systemctl disable --now vmware-modules-rebuild.service 2>/dev/null || true
|
||||
rm -f /etc/systemd/system/vmware-host.service \
|
||||
/etc/systemd/system/vmware-modules-rebuild.service \
|
||||
/usr/local/sbin/vmware-modules-rebuild.sh
|
||||
systemctl unmask vmware.service 2>/dev/null || true
|
||||
systemctl daemon-reload
|
||||
log "uninstalled (units removed, vmware.service unmasked)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -d "$SRC" ] || die "source dir not found: $SRC (clone the repo first)"
|
||||
command -v vmware-modconfig >/dev/null 2>&1 || warn "vmware-modconfig not found — is VMware Workstation installed?"
|
||||
[ -x /etc/init.d/vmware ] || warn "/etc/init.d/vmware not found — is VMware Workstation installed?"
|
||||
|
||||
# 1. rebuild guard script + units
|
||||
install -m 0755 -o root -g root "$SRC/vmware-modules-rebuild.sh" /usr/local/sbin/vmware-modules-rebuild.sh
|
||||
install -m 0644 -o root -g root "$SRC/vmware-modules-rebuild.service" /etc/systemd/system/vmware-modules-rebuild.service
|
||||
install -m 0644 -o root -g root "$SRC/vmware-host.service" /etc/systemd/system/vmware-host.service
|
||||
log "installed rebuild script + 2 systemd units"
|
||||
|
||||
# 2. mask the flaky sysv vmware.service so the native unit is the sole owner
|
||||
if [ "$(systemctl is-enabled vmware.service 2>/dev/null || true)" = "masked" ]; then
|
||||
log "vmware.service already masked"
|
||||
else
|
||||
systemctl mask vmware.service && log "masked sysv vmware.service" || warn "could not mask vmware.service"
|
||||
fi
|
||||
|
||||
# 3. reload + enable + start (start is idempotent — init script start is re-runnable)
|
||||
systemctl daemon-reload
|
||||
systemctl enable vmware-modules-rebuild.service
|
||||
systemctl enable vmware-host.service
|
||||
log "enabled vmware-modules-rebuild.service + vmware-host.service"
|
||||
|
||||
if systemctl start vmware-host.service; then
|
||||
log "vmware-host.service started"
|
||||
else
|
||||
warn "vmware-host.service start failed — check: journalctl -u vmware-host.service"
|
||||
fi
|
||||
|
||||
log "done — verify: lsmod | grep -E 'vmmon|vmnet'; ip -o link show | grep vmnet"
|
||||
Reference in New Issue
Block a user