v0.4.0: upload telemetry, host log, jet-black UI
- Upload reliability + diagnostics:
- api_upload_iso now distinguishes clean EOF from mid-stream errors;
a truncated multipart body (proxy buffer cap, network drop) returns
400 with the cause and a "try the LAN IP" hint instead of silently
finalising a partial file.
- Per-stage tracing (begin/MB-watermark/finish/abort) so a stuck
upload is debuggable from the Terminal tab.
- Web upload UI surfaces bytes/total, percent, throughput, ETA, and
maps 413/502/504/network-drop to actionable hints.
- New BootLog feature under Hosts:
- openpxe-core::BootLog — bounded in-memory ring (500) + append-only
JSONL on disk, recording (timestamp, mac, ip, target_id,
target_title) every time a boot entry script is served.
- iPXE per-entry chain URLs grow ?mac=${mac}; password prompt
submission carries it through; host-binding short-circuit uses the
bound MAC. ConnectInfo<SocketAddr> wired for peer IP capture (with
optional fallback so tower::oneshot in tests still works).
- GET /api/boot-log endpoint + Host log table under the Hosts tab.
- UI changes:
- Queue card header "Forge" → "Status".
- Removed Tinkerbell attribution sentence from Hosts tab.
- Topbar readiness chip moved into the sidebar footer as
"Service status: Ready / Advertised to clients / <url>", grouping
advertised PXE URL with operator-relevant status.
- Jet-black dark palette (#000 / #0a0a0a / #141414 / #1c1c1c)
replacing the blue-tinted ramp; terminal toolbar/input recoloured
to match.
- 89 tests passing (was 85 in v0.3.2); cargo clippy --workspace
--all-targets clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
115ba779da
commit
ec171ede47
@@ -103,6 +103,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
let queue = DeploymentQueue::new();
|
||||
let settings = SettingsStore::load_or_default(&config.paths.work_dir);
|
||||
let hosts = HostBindings::load_or_default(&config.paths.work_dir);
|
||||
let boot_log = openpxe_core::BootLog::load_or_default(&config.paths.work_dir);
|
||||
let metrics = Metrics::new();
|
||||
|
||||
// Build the SMB manager unconditionally — it starts/stops on the
|
||||
@@ -140,6 +141,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
settings: settings.clone(),
|
||||
queue: queue.clone(),
|
||||
hosts: hosts.clone(),
|
||||
boot_log: boot_log.clone(),
|
||||
metrics: metrics.clone(),
|
||||
smb: Some(smb.clone()),
|
||||
nfs: nfs.clone(),
|
||||
@@ -156,7 +158,15 @@ async fn main() -> anyhow::Result<()> {
|
||||
let http_task = tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind(http_addr).await?;
|
||||
tracing::info!(target: "openpxe::http", "HTTP listening on {http_addr}");
|
||||
axum::serve(listener, router).await?;
|
||||
// `into_make_service_with_connect_info` is required so per-request
|
||||
// `ConnectInfo<SocketAddr>` extractors can resolve the peer IP —
|
||||
// used by `/boot/<entry>.ipxe` to record the booting client's
|
||||
// address into the Host log. Without this the extractor 500s.
|
||||
axum::serve(
|
||||
listener,
|
||||
router.into_make_service_with_connect_info::<std::net::SocketAddr>(),
|
||||
)
|
||||
.await?;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user