diff --git a/Makefile b/Makefile index dc9d4df..81206b6 100644 --- a/Makefile +++ b/Makefile @@ -88,8 +88,10 @@ $(FRONTEND_WEB_DIST): $(FRONTEND_WEB_SRC) cd cmd/frontend/web && npm install && npm run build pkg-deb: build-amd64 build-arm64 - debian/build-deb.sh amd64 $(VERSION) - debian/build-deb.sh arm64 $(VERSION) + debian/build-deb.sh vpp-maglevd amd64 $(VERSION) + debian/build-deb.sh vpp-maglevd arm64 $(VERSION) + debian/build-deb.sh vpp-maglev amd64 $(VERSION) + debian/build-deb.sh vpp-maglev arm64 $(VERSION) test: $(GEN_FILES) go test ./... diff --git a/debian/build-deb.sh b/debian/build-deb.sh index 1bf9684..46aa0cc 100755 --- a/debian/build-deb.sh +++ b/debian/build-deb.sh @@ -1,64 +1,93 @@ #!/bin/bash -# Build a vpp-maglev Debian package for one architecture. -# Usage: build-deb.sh +# Build one vpp-maglev* Debian package for one architecture. +# Usage: build-deb.sh +# +# is one of: +# vpp-maglevd — health-checker daemon + optional web dashboard, +# with both systemd units, the default config, and +# the /etc/default/vpp-maglev environment file. +# vpp-maglev — maglevc CLI client and maglevt out-of-band tester. +# Pure client-side tools, no systemd units, no conffiles. # # The commit hash is baked into the binaries at link time via -ldflags -# in the Makefile, so `maglevd --version` / `maglevc --version` / -# `maglevd-frontend --version` are the source of truth for "which -# build". The .deb itself carries only the release version. +# in the Makefile, so `maglevd --version` / `maglevc --version` / etc. +# are the source of truth for "which build". The .deb itself carries +# only the release version. set -euo pipefail -ARCH="${1:?usage: build-deb.sh }" -VERSION="${2:?usage: build-deb.sh }" +PACKAGE="${1:?usage: build-deb.sh }" +ARCH="${2:?usage: build-deb.sh }" +VERSION="${3:?usage: build-deb.sh }" REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -PKG="vpp-maglev_${VERSION}_${ARCH}" +PKG="${PACKAGE}_${VERSION}_${ARCH}" STAGING="$(mktemp -d)" trap 'rm -rf "$STAGING"' EXIT echo "Building ${PKG}.deb" -# Directories -install -d "$STAGING/usr/sbin" -install -d "$STAGING/usr/bin" -install -d "$STAGING/usr/share/man/man1" -install -d "$STAGING/usr/share/man/man8" -install -d "$STAGING/lib/systemd/system" -install -d "$STAGING/etc/default" -install -d "$STAGING/etc/vpp-maglev" install -d "$STAGING/DEBIAN" -# Binaries. maglevd and maglevd-frontend are daemons and live under -# /usr/sbin; maglevc is the interactive CLI client and lives under -# /usr/bin so it's on every login shell's PATH. -install -m 755 "$REPO_ROOT/build/${ARCH}/maglevd" "$STAGING/usr/sbin/maglevd" -install -m 755 "$REPO_ROOT/build/${ARCH}/maglevc" "$STAGING/usr/bin/maglevc" -install -m 755 "$REPO_ROOT/build/${ARCH}/maglevd-frontend" "$STAGING/usr/sbin/maglevd-frontend" +case "$PACKAGE" in +vpp-maglevd) + install -d "$STAGING/usr/sbin" + install -d "$STAGING/usr/share/man/man8" + install -d "$STAGING/lib/systemd/system" + install -d "$STAGING/etc/default" + install -d "$STAGING/etc/vpp-maglev" -# Man pages -gzip -9 -c "$REPO_ROOT/docs/maglevd.8" > "$STAGING/usr/share/man/man8/maglevd.8.gz" -gzip -9 -c "$REPO_ROOT/docs/maglevc.1" > "$STAGING/usr/share/man/man1/maglevc.1.gz" -gzip -9 -c "$REPO_ROOT/docs/maglevd-frontend.8" > "$STAGING/usr/share/man/man8/maglevd-frontend.8.gz" + # Binaries. Both daemons live under /usr/sbin; they are long-running + # services, not interactive tools. + install -m 755 "$REPO_ROOT/build/${ARCH}/maglevd" "$STAGING/usr/sbin/maglevd" + install -m 755 "$REPO_ROOT/build/${ARCH}/maglevd-frontend" "$STAGING/usr/sbin/maglevd-frontend" -# Systemd units -install -m 644 "$REPO_ROOT/debian/vpp-maglev.service" "$STAGING/lib/systemd/system/vpp-maglev.service" -install -m 644 "$REPO_ROOT/debian/vpp-maglev-frontend.service" "$STAGING/lib/systemd/system/vpp-maglev-frontend.service" + # Man pages + gzip -9 -c "$REPO_ROOT/docs/maglevd.8" > "$STAGING/usr/share/man/man8/maglevd.8.gz" + gzip -9 -c "$REPO_ROOT/docs/maglevd-frontend.8" > "$STAGING/usr/share/man/man8/maglevd-frontend.8.gz" -# /etc/default/vpp-maglev (conffile — dpkg won't overwrite on upgrade) -install -m 644 "$REPO_ROOT/debian/default.vpp-maglev" "$STAGING/etc/default/vpp-maglev" + # Systemd units + install -m 644 "$REPO_ROOT/debian/vpp-maglev.service" "$STAGING/lib/systemd/system/vpp-maglev.service" + install -m 644 "$REPO_ROOT/debian/vpp-maglev-frontend.service" "$STAGING/lib/systemd/system/vpp-maglev-frontend.service" -# /etc/vpp-maglev/maglev.yaml (conffile) -install -m 644 "$REPO_ROOT/debian/maglev.yaml" "$STAGING/etc/vpp-maglev/maglev.yaml" + # /etc/default/vpp-maglev (conffile — dpkg won't overwrite on upgrade) + install -m 644 "$REPO_ROOT/debian/default.vpp-maglev" "$STAGING/etc/default/vpp-maglev" -# DEBIAN/control -sed "s/@VERSION@/${VERSION}/;s/@ARCH@/${ARCH}/" \ - "$REPO_ROOT/debian/control.in" > "$STAGING/DEBIAN/control" + # /etc/vpp-maglev/maglev.yaml (conffile) + install -m 644 "$REPO_ROOT/debian/maglev.yaml" "$STAGING/etc/vpp-maglev/maglev.yaml" -# DEBIAN/conffiles, postinst, prerm, postrm -install -m 644 "$REPO_ROOT/debian/conffiles" "$STAGING/DEBIAN/conffiles" -install -m 755 "$REPO_ROOT/debian/postinst" "$STAGING/DEBIAN/postinst" -install -m 755 "$REPO_ROOT/debian/prerm" "$STAGING/DEBIAN/prerm" -install -m 755 "$REPO_ROOT/debian/postrm" "$STAGING/DEBIAN/postrm" + # DEBIAN metadata + sed "s/@VERSION@/${VERSION}/;s/@ARCH@/${ARCH}/" \ + "$REPO_ROOT/debian/vpp-maglevd.control.in" > "$STAGING/DEBIAN/control" + install -m 644 "$REPO_ROOT/debian/vpp-maglevd.conffiles" "$STAGING/DEBIAN/conffiles" + install -m 755 "$REPO_ROOT/debian/vpp-maglevd.postinst" "$STAGING/DEBIAN/postinst" + install -m 755 "$REPO_ROOT/debian/vpp-maglevd.prerm" "$STAGING/DEBIAN/prerm" + install -m 755 "$REPO_ROOT/debian/vpp-maglevd.postrm" "$STAGING/DEBIAN/postrm" + ;; + +vpp-maglev) + install -d "$STAGING/usr/bin" + install -d "$STAGING/usr/share/man/man1" + + # Binaries. Both client tools live under /usr/bin so they land on + # every login shell's PATH without needing /usr/sbin on PATH. + install -m 755 "$REPO_ROOT/build/${ARCH}/maglevc" "$STAGING/usr/bin/maglevc" + install -m 755 "$REPO_ROOT/build/${ARCH}/maglevt" "$STAGING/usr/bin/maglevt" + + # Man pages + gzip -9 -c "$REPO_ROOT/docs/maglevc.1" > "$STAGING/usr/share/man/man1/maglevc.1.gz" + gzip -9 -c "$REPO_ROOT/docs/maglevt.1" > "$STAGING/usr/share/man/man1/maglevt.1.gz" + + # DEBIAN metadata. The client package has no conffiles and no + # maintainer scripts — it ships binaries and manpages only. + sed "s/@VERSION@/${VERSION}/;s/@ARCH@/${ARCH}/" \ + "$REPO_ROOT/debian/vpp-maglev.control.in" > "$STAGING/DEBIAN/control" + ;; + +*) + echo "error: unknown package '${PACKAGE}' (expected vpp-maglevd or vpp-maglev)" >&2 + exit 2 + ;; +esac # Emit package into build/ mkdir -p "$REPO_ROOT/build" diff --git a/debian/vpp-maglev.control.in b/debian/vpp-maglev.control.in new file mode 100644 index 0000000..f0c06ef --- /dev/null +++ b/debian/vpp-maglev.control.in @@ -0,0 +1,22 @@ +Package: vpp-maglev +Version: @VERSION@ +Architecture: @ARCH@ +Maintainer: Pim van Pelt +Section: net +Priority: optional +Description: Maglev CLI client and out-of-band VIP tester + maglevc is an interactive CLI client for maglevd with tab completion, + inline help, and a one-shot mode for scripting. It talks to maglevd + over gRPC and can drive either a local daemon or a remote one. + . + maglevt is an out-of-band HTTP probe TUI that reads a maglev.yaml, + hits each configured frontend on a configurable HTTP path, and + reports latency plus a response-header tally so operators can see + Maglev failover as it happens. It does not talk gRPC and does not + depend on a running maglevd; it is useful for validating a maglevd + restart end-to-end from a client perspective and for debugging pool + failover. + . + Install alongside the vpp-maglevd package to manage a local daemon, + or install standalone on a jump host or operator workstation to + manage remote maglevds over gRPC. diff --git a/debian/conffiles b/debian/vpp-maglevd.conffiles similarity index 100% rename from debian/conffiles rename to debian/vpp-maglevd.conffiles diff --git a/debian/control.in b/debian/vpp-maglevd.control.in similarity index 56% rename from debian/control.in rename to debian/vpp-maglevd.control.in index fba609b..de8ba7e 100644 --- a/debian/control.in +++ b/debian/vpp-maglevd.control.in @@ -1,19 +1,21 @@ -Package: vpp-maglev +Package: vpp-maglevd Version: @VERSION@ Architecture: @ARCH@ Maintainer: Pim van Pelt Section: net Priority: optional Depends: systemd, adduser -Description: Maglev health-checker daemon, CLI client, and web frontend +Recommends: vpp-maglev +Description: Maglev health-checker daemon and web frontend for the VPP lb plugin maglevd monitors backends (HTTP, TCP, ICMP) with a rise/fall counter - model and exposes their aggregated state over a gRPC API. Configuration + model, programs the VPP lb plugin via its binary API, and exposes the + result over a gRPC API and Prometheus metrics endpoint. Configuration is loaded from a YAML file and supports live reload via SIGHUP. . - maglevc is an interactive CLI client for maglevd with tab completion, - inline help, and one-shot mode for scripting. - . maglevd-frontend is an optional web dashboard that fans one or more maglevd gRPC streams out to browsers over Server-Sent Events. It is installed but not enabled by default; enable with: systemctl enable --now vpp-maglev-frontend + . + The maglevc CLI client and the maglevt out-of-band tester live in + the vpp-maglev package (recommended but not required). diff --git a/debian/postinst b/debian/vpp-maglevd.postinst similarity index 100% rename from debian/postinst rename to debian/vpp-maglevd.postinst diff --git a/debian/postrm b/debian/vpp-maglevd.postrm similarity index 100% rename from debian/postrm rename to debian/vpp-maglevd.postrm diff --git a/debian/prerm b/debian/vpp-maglevd.prerm similarity index 100% rename from debian/prerm rename to debian/vpp-maglevd.prerm diff --git a/docs/maglevt.1 b/docs/maglevt.1 new file mode 100644 index 0000000..3f3456c --- /dev/null +++ b/docs/maglevt.1 @@ -0,0 +1,141 @@ +.TH MAGLEVT 1 "April 2026" "vpp\-maglev" "User Commands" +.SH NAME +maglevt \- Maglev out\-of\-band VIP probe TUI +.SH SYNOPSIS +.B maglevt +[\fB\-config\fR \fIfile\fR]... +[\fB\-interval\fR \fIdur\fR] +[\fB\-timeout\fR \fIdur\fR] +[\fB\-host\fR \fIstr\fR] +[\fB\-uri\fR \fIpath\fR] +[\fB\-header\fR \fIname\fR] +[\fB\-insecure\fR[=\fIbool\fR]] +[\fB\-keepalive\fR] +[\fB\-filter\fR \fIregex\fR] +[\fB\-version\fR] +.SH DESCRIPTION +.B maglevt +is an out\-of\-band VIP probe TUI for +.B vpp\-maglev +deployments. It reads one or more +.B maglev.yaml +configuration files, enumerates the configured TCP/HTTP frontends, and +probes each one on a configurable HTTP path at a configurable interval. +It does not talk gRPC, does not depend on a running +.BR maglevd (8), +and reports its results as a live full\-screen TUI rather than to any +machine\-readable channel. +.PP +Typical uses: +.IP \(bu 2 +Validate a +.B maglevd +restart end\-to\-end from a client perspective. The probe tally keeps +running independently of the control plane, so a brief dataplane blip +or a missed failover is visible directly in the TUI. +.IP \(bu 2 +Debug pool failover. With keep\-alives off (the default), each probe +opens a fresh TCP connection and is reshuffled by VPP's Maglev hash, +so the response\-header tally visibly changes the moment a standby +pool takes over. +.IP \(bu 2 +Sanity\-check VIP reachability across sites when the gRPC control +plane is unavailable or out of reach from the operator's machine. +.SH OPTIONS +.TP +.BI \-config " file" +Path to a +.B maglev.yaml +configuration file. The flag is repeatable and also accepts a +comma\-separated list. Frontends are unioned across all supplied files +and de\-duplicated by +.IR "(scheme, address, port)" , +so the same VIP is never probed twice even when multiple files +reference it. +.RI "(default: " /etc/vpp-maglev/maglev.yaml ) +.TP +.BI \-interval " dur" +Probe interval per VIP. Uniform +.B \(+-10% +jitter is applied per probe to prevent phase\-locking after a +restart. +.RI "(default: " 100ms ) +.TP +.BI \-timeout " dur" +Per\-request timeout. Bounds a single probe attempt; the interval +bounds the time between the +.I start +of consecutive attempts. +.RI "(default: " 2s ) +.TP +.BI \-host " str" +Override for the HTTP +.B Host +header. When unset, +.B maglevt +uses the VIP's address literal as the +.B Host +header. +.TP +.BI \-uri " path" +HTTP request path used in the +.B GET +request. The flag +.B \-path +is accepted as an alias. +.RI "(default: " /.well-known/ipng/healthz ) +.TP +.BI \-header " name" +Response header whose value is extracted and tallied, so the TUI can +show which backend served each request. +.RI "(default: " X-IPng-Frontend ) +.TP +.B \-insecure +Skip TLS certificate verification for HTTPS frontends. +.RI "(default: " true ) +.TP +.BR \-keepalive ", " \-k +Enable HTTP keep\-alives. Off by default: every probe opens a fresh +connection, which is necessary for failover visibility because a +pinned keep\-alive would mask a Maglev reshuffle. +.RI "(default: " false ) +.TP +.BI \-filter " regex" +Regular expression restricting which frontends are probed; only +frontends whose name matches are included. +.TP +.B \-version +Print version, commit hash, and build date, then exit. +.SH "USER INTERFACE" +The TUI is built with Bubble Tea and shows a deterministic grid: one +tile per VIP, with IPv6 tiles before IPv4 and HTTPS before HTTP so the +layout is stable across runs and across machines. Each tile carries a +rolling latency summary (min, max, average, and several percentiles), +running success and failure counts, and a tally of the configured +response\-header values seen from that VIP. +.PP +Press +.B d +to toggle reverse\-DNS resolution on the addresses shown in the tile +headers. Press +.B q +or Ctrl\-C to exit. There is no machine\-readable output; use the +Prometheus +.B /metrics +endpoint on +.BR maglevd (8) +when you need metrics. +.SH "FULL DOCUMENTATION" +This manpage documents only the invocation of +.BR maglevt . +For the full operational guide see the user guide at: +.PP +.RS +https://git.ipng.ch/ipng/vpp-maglev/docs/user-guide.md +.RE +.SH "SEE ALSO" +.BR maglevd (8), +.BR maglevc (1), +.BR maglevd\-frontend (8) +.SH AUTHOR +Pim van Pelt