feat(daemon): scaffold traffic_shaper monitor skeleton in solo-provisioner-daemon#792
Merged
Merged
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
4340bc3 to
7be88ae
Compare
…ioner-daemon Turn the block-node traffic_shaper monitor from a no-op stub into the daemonkit-supervised skeleton for epic TS_3. Run now launches the pod-lifecycle watcher and statusz poll loop concurrently, each retried in place with 5s->5min exponential back-off so a subsystem fault never kills the daemon. Monitor health is exposed via GET /block_node/traffic_shaper/status. Both responsibility bodies remain stubs; the real veth/HTB/statusz/nft logic lands in sibling stories (#747-#755, #774). Closes #746 Signed-off-by: alex-au <alex.w.aus@gmail.com> Signed-off-by: Bruno Marques <bruno.marques@swirldslabs.com>
7be88ae to
09e8f65
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Stands up the block-node
traffic_shapermonitor as a realdaemonkit-supervisedcomponent inside
solo-provisioner-daemon— the structural skeleton that the rest ofepic TS_3 (#736) hangs off. Until now the monitor was a no-op stub that logged once
and blocked on
ctx. It now runs its two long-lived responsibilities concurrently andreports its health over the daemon socket.
Run(ctx)launches the pod-lifecycle watcher and the statusz poll loop as twogoroutines, each wrapped in a per-responsibility retry loop with 5 s → 5 min
exponential back-off. A fault in one responsibility is logged and retried in place and is
never propagated to
Run, so a subsystem fault can't stop the other responsibility, tripthe top-level supervisor, or kill the daemon process. Monitor health (supervisor
running/backoff/stopped) is exposed viaGET /block_node/traffic_shaper/status.This is skeleton only: both responsibility bodies are stubs. The real veth resolution,
ingress HTB attach, statusz client, category→policy diff, nft membership apply, bootstrap
sequencing, and privileged-exec delegation land in sibling stories (#747–#755, #774). The
degradedhealth state and alerting are owned by #750 — this PR reports only supervisorstate.
Files changed
internal/daemon/blocknode/traffic_shaper_monitor.goTrafficShaperMonitor;Runlaunches the two responsibilities viasuperviseResponsibility(5 s → 5 min back-off, faults swallowed); stubrunPodWatcher/runStatuszPollbodiesinternal/daemon/blocknode/handler.goBlockNodeHandler(daemonkit.ComponentHandler) servingGET /block_node/traffic_shaper/status; 503 when monitor disabledinternal/daemon/blocknode/component.goComponentResultcarries*TrafficShaperMonitorfor handler wiringinternal/daemon/daemon.gotrafficShaperStateFnclosure over the componentStatusTrackerand registersBlockNodeHandlerinternal/daemon/blocknode/traffic_shaper_monitor_test.gointernal/daemon/blocknode/handler_test.gointernal/templates/files/weaver/solo-provisioner-daemon.serviceReadWritePathsis now a Go template; paths beyond/opt/soloare rendered conditionally at install timeinternal/workflows/daemon.godaemonExtraReadWritePaths(cfg)derives the per-component extra paths; passes them toInstallDaemonServiceStepinternal/workflows/steps/step_daemon.goInstallDaemonServiceStepacceptsextraReadWritePaths []string; creates each path before rendering the service unit — fixes status=226/NAMESPACE on BN-only hosts where/opt/hgcappis absentReview guide
Code review checklist
traffic_shaper_monitor.go—superviseResponsibilitynever returns a non-nil error: a faultingfnis logged + retried, and the loop exits only onctxcancellation. This is the core invariant ("no process death on subsystem fault" from Story 3.1 —traffic_shapermonitor skeleton insolo-provisioner-daemon#746).traffic_shaper_monitor.go— back-off floor is 5 s (issue-specified), cap 5 min, factor 2.0;responsibilityBackoffInitial/Maxarevar(notconst) only so tests can shrink them — production never reassigns.traffic_shaper_monitor.go—Runwaits on both responsibilities (sync.WaitGroup) and returnsnilonly after both stop on ctx cancel, keeping the top-leveldaemonkit.SupervisedMonitorcontract intact.daemon.go—trafficShaperStateFncloses overcomp.trackeraftercompis appended to the slice (value copy is fine —trackeris a pointer), mirroring the consensus-handler wiring; handler only added whenresult.TrafficShaperMonitor != nil.handler.go—GET /block_node/traffic_shaper/statusreturns 503 whenmon == nil(disabled) and otherwise the supervisorMonitorState; nodegradedfield yet (deferred to Story 3.5 — Monitor health: degraded state,/status, and alerting #750). Covered byTestBlockNodeHandler_NilMonitor_Returns503.component.go—NewComponentreturns the monitor reference; enablement is still gated byblock_node.monitors.traffic_shaperindaemon.yaml(unchanged).step_daemon.go—InstallDaemonServiceSteptakesextraReadWritePaths []string(no CN knowledge);daemonExtraReadWritePaths(cfg)indaemon.gois the single place that maps component config → required paths. Adding a future component's data root is a one-liner there with no touch to the step.solo-provisioner-daemon.service—ReadWritePaths=/opt/solo{{range .ExtraReadWritePaths}} {{.}}{{end}}renders cleanly toReadWritePaths=/opt/soloon BN-only installs andReadWritePaths=/opt/solo /opt/hgcappwhen CN is enabled. Any listed path that is absent at service start causes status=226/NAMESPACE — theMkdirAllloop in the step must run beforeinstallDaemonServiceFiles.Unit tests
Manual UAT
Exercises the live
/block_node/traffic_shaper/statusendpoint over the daemon's unixsocket. Run inside the UTM VM (Linux, arm64).
Step 1 — Build and copy the daemon binary to the VM
Step 2 — Install the daemon service
This single command:
/opt/solo/weaver/config/daemon.yamlwithblock_node.enabled: trueandmonitors.traffic_shaper: true/opt/solo/weaver/bin/solo-provisioner-daemonsolo-provisioner-daemon.servicesystemd unitStep 3 — Verify the service is healthy
Expected: all checks pass.
Step 4 — Confirm startup log lines
Expected log lines (in order):
Step 5 — Query the traffic-shaper status endpoint
The daemon socket (
/opt/solo/weaver/daemon/daemon.sock) is owned byweaver:weaver(
srw-rw----). Usesudoor add your user to theweavergroup before querying:Expected HTTP 200:
{"monitor":{"state":"running"}}Risks / rollback
block_node.enabled+monitors.traffic_shaper; with themonitor disabled, daemon behavior is unchanged.
superviseResponsibilitymust never propagate a fault toRun— a regression there lets a stub fault bubble up and trip the top-level supervisor.Covered by
TestSuperviseResponsibility_RetriesFaultsWithoutPropagating.{{range .ExtraReadWritePaths}}— any path added tothe template data that does not exist at service start causes status=226/NAMESPACE. The
MkdirAllloop inInstallDaemonServiceStep.Executemust always run beforeinstallDaemonServiceFiles. Covered by integration tests instep_daemon_it_test.go.Related Issues
traffic_shapermonitor skeleton insolo-provisioner-daemon#746