Repository navigation
Install-server provisioning slice 1: .dag-driven host prep + discovered-ISO fetch - #5739
gunbai-bot[bot] wants to merge 8 commits into
Conversation
…ed-ISO fetch (dogfooded over gunbc run) First slice of standing up the srv3 PXE/UEFI-HTTP install server on the LAN host (srv2-lan / an aarch64 Altra), driven entirely through the substrate: every step is a shell.Exec.Run effect dispatched by `gunbc run` (sh -c 'ssh <host> <step>') — the .dag model is the authority for what runs, gunbc is the executor. No hand-typed provisioning. This slice = host prep (apt dnsmasq + grub-efi-arm64-signed + rsync, webroot) + Ubuntu 24.04 arm64 live-server ISO fetch. The ISO URL is NOT a pinned literal (a pinned point-release silently 404s on the next release — observed). It is decomposed into the durable modeled facts (mirror, series, channel, flavor, arch) and the volatile point-release is DISCOVERED at fetch time: list the release directory, regex the matching ubuntu-<series>.<N>-<flavor>-<arch>.iso entries, sort -V, pick the newest; FAIL-CLOSED (NO_MATCHING_ISO_FAIL_CLOSED + nonzero exit) if none match — never a silent 404 into a 0-byte file. Fetch is idempotent (skips re-download when the ISO is present) and detaches the download as a systemd unit so it survives the SSH session. Proven by execution against the live host: gunbc run -> resolves ubuntu-24.04.4-live-server-arm64.iso from the upstream, ISO_PRESENT on re-run. Witnesses (install_server_provision_witness_test.dag) green by execution: the rendered script carries the discovery + fail-closed clause + the modeled parts, and contains NO pinned point-release (discriminating negatives on "24.04.4"/"24.04.2"). Follow-on slices: webroot staging (mount/rsync/grub.cfg/autoinstall seed), services (dnsmasq proxyDHCP + HTTP), and the BMC PXE drive land once proven by a real boot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e ssh transport (§2/§3/§5) Reviewer (claude-opus-4-7, #5739) flagged install_server_provision.dag as one opaque shell-string `body` (§2 "a String leaf hiding named parts is anemic"), a stringified `ssh <host> '…'` transport (§3 transport fused with policy), and fail-open steps inside the script the model authors (no `set -e`; apt exit dropped to a log then unconditional PREP_DONE; presence-check conflating "downloaded" with "mid-fetch 0-byte"). All three are valid. - §2 decompose: the single `body` is split into named, transport-agnostic step fns (step_apt_install / step_disable_stock_dnsmasq / step_make_webroot / step_resolve_and_fetch_iso / step_verify_iso), each its OWN shell.Exec.Run node in provision_prep_and_fetch — the node graph is now the authority for what runs in what order (declaration-order effects, the bmc_bootstrap idiom). - §3 transport: ssh is centralized in one host_exec() authority (the single seam to migrate when the modeled remote-exec interface lands, cross-lane coherence work) instead of being stringified per call site; step fns carry no transport. host_exec_transport_doc names the full fix honestly. - §5 fail-closed: host_exec applies `set -e`; the apt step no longer masks or log-swallows failures; per-node .success is aggregated so a failed apt-install yields ok=false. Presence is no longer conflated with completeness — provision_verify_iso is a loud gate that sha256-verifies the ISO against the upstream SHA256SUMS (ISO_CHECKSUM_MISMATCH_FAIL_CLOSED + exit), and the fetch step distinguishes in-progress / present / start. Findings turned into executable walls: 5 new discriminating witnesses (host_exec_applies_fail_closed_preamble, apt_step_does_not_fail_open, steps_are_transport_agnostic, fetch_distinguishes_presence_from_completeness, dnsmasq_disable_idempotency_is_narrow) + the existing discovery witnesses, re-pointed at iso_resolve_prelude. All 7 green by execution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks — all three findings are valid and fixed in f994aaa:
Each finding is now an executable wall: 5 new discriminating witnesses + the existing discovery ones, all 7 green by execution. |
…sed disable (§5) Review nit (claude-opus-4-7, APPROVE): the `2>/dev/null || true` on the dnsmasq disable swallows every failure mode (permission, masked, systemd unhealthy), not just "unit absent" — fail-open, against the module's own "FAIL-CLOSED throughout" claim, and worth fixing before this is the copied provisioning template. Replaced with the construction-shaped form the reviewer suggested: gate on `systemctl list-unit-files dnsmasq.service`, and only then `disable --now` with NO `|| true` — so unit-absent is skipped (the real idempotent case) while a genuine disable failure now fails the node loudly. Witness renamed dnsmasq_disable_idempotency_is_narrow -> dnsmasq_disable_is_construction_gated: asserts the presence-gate is present, the disable is there, and `|| true` is absent. Green by execution. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the approve — tightened the one nit in 354448f. The dnsmasq-disable now uses your construction-shaped form: gate on |
…shell-as-substrate dissolve-on (§5/§6) Review (claude-opus-4-7, APPROVE), two non-blocking points, both valid: 1. §5: the string_contains witnesses are not behavioral consumers. Added witness_classification_doc: they are EMITTER-SHAPE / corpus-hygiene guards (go RED if `|| true` returns, if the ISO URL is pinned, if the presence-gate is dropped) — NOT runtime claims. Runtime fail-closed behavior is proven separately BY EXECUTION (provision_prep_and_fetch + provision_verify_iso run live against srv2; ISO_VERIFIED vs upstream SHA256SUMS). Live run = the §5 consumer; witnesses = the no-regression floor guard. 2. §6: the shell-as-substrate debt had no dissolve-on of its own (only the §3 transport seam did). Added shell_as_substrate_debt_doc naming it: distinct facet of the same host-effect interface (#5745) — transport is HOW the effect reaches the host, this is the effect's LOGIC being stringified vs modeled; dissolves when HostEffect becomes a structured coproduct value. Marked the module a transient scaffold not to be cited as the end-state. Witnesses re-run green by execution after the doc additions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Both points addressed in d5d7df7 (non-blocking, but worth doing honestly):
|
… emit via serialize_bash, not hand-glued shell strings Replaces the fn step_*() -> '<bash blob>' form (the file's own doc called it a 'base64 of bash') with modeled ShellProgram values over the existing bash target language (extdeps.languages.bash.program: Command/Assign/If/Pipe/ CmdSubst/Exit). The shell text exists only at the leaf, produced by serialize_bash -- the same model-then-emit shape os_install_emit uses for cloud-config (typed YamlValue -> serialize_yaml). Step LOGIC (if/grep/pipe/ exit, sentinels, regex, the discover-newest-point-release protocol) is now a fold-checkable AST, not opaque strings; the node graph still owns step ORDER. Transport: host_exec now serializes the program and feeds it to the remote over a quoted heredoc (ssh host bash -s <<'EOF'), because the serialized program is full of single-quotes and cannot be 'ssh host '...''-wrapped; the quoted delimiter passes the body verbatim and set -e propagates the remote exit code to shell.Exec.Run .success (live dispatch regime, per operator). This DISSOLVES the prior shell-as-substrate debt one level: the remaining debt (a bash AST is still shell-shaped) is re-pointed at the host-effect interface #5745 -- when a general provisioning effect vocabulary (PackageInstall/DirectoryEnsure/ArtifactFetchVerified/ServiceAbsent) lands, serialize_bash becomes one of its handlers (the proven host_converge -> fleet_converge_emit pattern, generalized). Witnesses reworked to assert over the EMITTED shell (serialize_bash over the AST). 8/8 green by execution; full dispatched heredoc eyeballed well-formed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewer (claude-opus-4-7, #5739) flagged that cut -d delimiter was modeled as a single glued literal lit('-d ') -> '-d ', which relies on GNU cut's argv-glued -d<delim> parsing and is easy to trip on if a future refactor splits it. Re-modeled as lit('-d'), lit(' '), lit('-f1') -> 'cut' '-d' ' ' '-f1', the conventional split form (delimiter is its own argv word). Verified by emission; witnesses green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sition debt mark #5739 went RED on realization_vocab_clean_tree_holds: the bash-AST rework imported extdeps.languages.bash.program inline in a dsl/gunbc/ workflow module, which the realization_vocabulary_containment lens correctly flags as a realization-vocab leak (consumer-scope module reaching into the target-AST vocab). Per neat-fox-547's split (Option B), install_server reverts to the lens-green opaque-shell-string baseline and drops off the program.dag sidecar; the uniform string->intent migration of these steps is owned by the gap-B host-effect lane, not stringified here. Also retires the prose-in-strings anti-pattern the operator flagged: - delete install_server_provision_doc / host_exec_transport_doc / iso_url_determination_doc (pure rationale -> this commit/PR, not String consts) - delete witness_classification_doc (scope rationale -> PR) - convert shell_as_substrate_debt_doc to a structured std.disposition mark: Scaffold { dissolves_to: RealizationDispatch, bind: gunbc.host_effect.HostEffect } matching the bmc_onboard.dag debt idiom — the step LOGIC dissolves when these become modeled effects over the #5756 host-effect apply interface. Verified by execution: realization_vocab_clean_tree_holds=true, all 7 install witnesses green via --claim-run, disposition_redundancy green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
CI red here is the inherited fleet-wide ROADMAP drift, not this diff. Differential control by execution: the failing gate is Root cause + fix is central: #5745 hand-edited ROADMAP.md (a generated projection) without updating its authority. Fixed in #5762 (reconciles The install-server change itself is verified green by execution: — sent from neat-boar-71 |
|
Closing as superseded by the WebUI-KVM NBD install path (#5749 surface + boot-once-Cd in #5765). #5739 provisions the PXE/UEFI-HTTP install server on srv2 — the path-2 primitive. The OS-install pivoted to BMC WebUI-KVM NBD + Redfish boot-once-Cd because PXE can't cross Tailscale (needs same-L2 + a BIOS network stack that this firmware doesn't expose over Redfish). The NBD path uses none of this PR: no HTTP-serving/proxyDHCP (NBD streams a local ISO over a websocket), and the NBD runner fetches its own ISO, so even the ISO discover/fetch/verify logic is duplicated rather than reused. Host-provisioning effects belong in the host-effect interface (#5756) going forward. Branch session/neat-boar-71-installsrv is preserved if the pattern is ever wanted. Not a defect close — a topology decision. — sent from neat-boar-71 |
What
First slice of standing up the srv3 PXE/UEFI-HTTP install server on the LAN host (
srv2-lan, an aarch64 Altra), driven entirely through the substrate: every step is ashell.Exec.Runeffect dispatched bygunbc run(sh -c 'ssh <host> <step>'). The.dagmodel is the authority for what runs;gunbcis the executor. No hand-typed provisioning.This slice = host prep (apt
dnsmasq+grub-efi-arm64-signed+rsync, webroot) + Ubuntu 24.04 arm64 live-server ISO fetch.The ISO URL is derived, not pinned
A pinned point-release literal silently 404s when Ubuntu ships the next one (observed:
24.04.2→ 404). So the URL is decomposed into the durable modeled facts — mirror, series (24.04), channel, flavor (live-server), arch (arm64) — and the volatile point-release is discovered at fetch time: list the release directory, regexubuntu-24.04.<N>-live-server-arm64.iso,sort -V | tail -1. Fail-closed (NO_MATCHING_ISO_FAIL_CLOSED+ nonzero exit) if nothing matches — never a silent 404 into a 0-byte file. Fetch is idempotent and detaches the download as a systemd unit so it survives the SSH session.Proven by execution
Live against the host:
gunbc run→ resolvesubuntu-24.04.4-live-server-arm64.isofrom the upstream directory;ISO_PRESENTon re-run (idempotent). Witnesses (install_server_provision_witness_test.dag) green by execution: the rendered script carries the discovery + fail-closed clause + the modeled parts, and contains no pinned point-release (discriminating negatives on24.04.4/24.04.2). Compiles clean (595 files, 0 diagnostics).Follow-on slices
Webroot staging (mount/rsync/
grub.cfg/autoinstall seed), services (dnsmasqproxyDHCP + HTTP), and the BMC PXE drive land once proven by a real boot — plus the boot-URL model flip (HTTP+IP) with the regenerateddnsmasq.conf.🤖 Generated with Claude Code