#!/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"