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.
91 lines
4.1 KiB
Bash
Executable File
91 lines
4.1 KiB
Bash
Executable File
#!/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"
|