metalman: make PXE bootstrap resilient - #540
Draft
Jordan Olshevski (jveski) wants to merge 43 commits into
Draft
Conversation
Jordan Olshevski (jveski)
commented
Jul 22, 2026
Contributor
- add durable, immutable netboot endpoint and session APIs
- split Metalman control, server, and edge runtime roles
- orchestrate bootstrap networking and handoff from kubectl
- add session-scoped DHCP, HTTP, TFTP, TLS, and recovery coverage
Contributor
There was a problem hiding this comment.
Pull request overview
This PR redesigns Metalman netboot provisioning around durable, immutable NetbootEndpoint/NetbootSession APIs and splits Metalman into controller/server/edge roles, enabling resilient bootstrapping and session-scoped DHCP/TFTP/HTTP/callback flows (including bootstrap-netboot orchestration from kubectl unbounded).
Changes:
- Introduces cluster-scoped NetbootEndpoint/NetbootSession types + CRDs, and updates operator bootstrap requirements and migration behavior.
- Splits Metalman runtime roles (controller/server/edge) and adds session-scoped artifact serving, callbacks, edge-authenticated DHCP decisions, and resumable backend artifact streaming.
- Refactors unbounded-net node agent into an importable
nodeagentpackage and adds bootstrap/external gateway helpers; updates smoke tests and docs accordingly.
Reviewed changes
Copilot reviewed 118 out of 119 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/operator/migrate.go | Drops legacy Metalman DHCP auto-interface translation; only detects enablement. |
| internal/operator/migrate_test.go | Updates migration tests to assert removed DHCP flag is not preserved. |
| internal/operator/migrate_gates_test.go | Updates hardening tests to ignore removed DHCP flag conflicts. |
| internal/operator/bootstrap.go | Adds new required CRDs for netboot endpoints/sessions. |
| internal/operator/bootstrap_test.go | Updates required-CRD list test for netboot CRDs. |
| internal/net/nodeagent/wireguard_config.go | Moves node agent code into nodeagent package. |
| internal/net/nodeagent/wireguard_config_test.go | Aligns tests with nodeagent package rename. |
| internal/net/nodeagent/tunnel_interface_validation.go | Package rename to nodeagent. |
| internal/net/nodeagent/tunnel_interface_validation_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/tunnel_config.go | Package rename to nodeagent. |
| internal/net/nodeagent/status_server.go | Package rename to nodeagent. |
| internal/net/nodeagent/status_server_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/status_server_http_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/status_proto.go | Package rename to nodeagent. |
| internal/net/nodeagent/status_proto_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/site_watch_reconcile.go | Adds gateway membership helper + CNI management helper; package rename. |
| internal/net/nodeagent/site_watch_reconcile_test.go | Adds tests for site-less gateway membership + CNI behavior. |
| internal/net/nodeagent/runtime_utils.go | Package rename to nodeagent. |
| internal/net/nodeagent/runtime_utils_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/route_annotations.go | Package rename to nodeagent. |
| internal/net/nodeagent/reconciliation_helpers.go | Package rename to nodeagent. |
| internal/net/nodeagent/reconciliation_helpers_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/reconciliation_helpers_more_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/reconciliation_helpers_bfd_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/peer_healthcheck.go | Package rename to nodeagent. |
| internal/net/nodeagent/node_types.go | Package rename to nodeagent. |
| internal/net/nodeagent/node_config_validation.go | Package rename to nodeagent. |
| internal/net/nodeagent/node_config_validation_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/metrics.go | Package rename to nodeagent. |
| internal/net/nodeagent/main_update_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/main_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/main_config_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/link_stats_monitor.go | Package rename to nodeagent. |
| internal/net/nodeagent/link_stats_monitor_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/kube_proxy_monitor.go | Package rename to nodeagent. |
| internal/net/nodeagent/kube_proxy_monitor_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/gateway_routes.go | Package rename to nodeagent. |
| internal/net/nodeagent/gateway_routes_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/external.go | Adds “external gateway” config + runner for bootstrap routing. |
| internal/net/nodeagent/external_test.go | Tests safe defaults/validation for external gateway config. |
| internal/net/nodeagent/encapsulation.go | Package rename to nodeagent. |
| internal/net/nodeagent/encapsulation_test.go | Package rename to nodeagent. |
| internal/net/nodeagent/bpf_status.go | Package rename to nodeagent. |
| internal/net/nodeagent/bootstrap_helpers.go | Package rename to nodeagent. |
| internal/net/nodeagent/bootstrap_helpers_test.go | Package rename to nodeagent. |
| internal/metalman/netboot/tftp.go | Adds configurable TFTP port + backend streaming support for session artifacts. |
| internal/metalman/netboot/tftp_backend.go | Implements resumable HTTP-backed artifact reader + milestone callback posting. |
| internal/metalman/netboot/tftp_backend_test.go | Adds tests for backend artifact streaming + resume behavior. |
| internal/metalman/netboot/session_dhcp_test.go | Adds tests for session-scoped DHCP decision API behavior. |
| internal/metalman/netboot/oci_cache.go | Adds digest-based cache resolution API for immutable sessions. |
| internal/metalman/netboot/netboot.go | Extends template data to support session-scoped URLs and callbacks. |
| internal/metalman/netboot/netboot_test.go | Updates tests for transport rename and related behaviors. |
| internal/metalman/netboot/http.go | Switches HTTP boot gating to transport-based checks. |
| internal/metalman/netboot/edge_auth.go | Adds TokenReview-based edge authenticator for internal edge APIs. |
| internal/metalman/netboot/edge_auth_test.go | Tests TokenReview edge authentication behavior. |
| internal/metalman/netboot/capability.go | Adds HMAC-signed session capability issuing/verification. |
| internal/metalman/machineops/session_status.go | Adds recorder to latch milestones on exact session + operation target. |
| internal/metalman/machineops/session_status_test.go | Tests exact-session/target status updates and stale UID rejection. |
| internal/metalman/machineops/session_manager_test.go | Adds session manager tests for digest snapshotting + reuse rules. |
| internal/metalman/dhcp/dhcp.go | Introduces DecisionProvider abstraction for session-based DHCP decisions. |
| internal/metalman/dhcp/dhcp_test.go | Adds DHCP test coverage for backend session decision flow. |
| internal/metalman/dhcp/backend.go | Adds HTTPDecisionProvider for edge-to-server DHCP decisions. |
| internal/metalman/dhcp/backend_test.go | Tests decision provider auth, 404-as-nil, and token reload. |
| internal/metalman/commands/server.go | Adds metalman server role command entrypoint. |
| internal/metalman/commands/serve_pxe.go | Refactors legacy serve-pxe into role-driven wiring (controller/server/edge/legacy). |
| internal/metalman/commands/roles.go | Defines Metalman roles and which components each role runs. |
| internal/metalman/commands/roles_test.go | Tests role isolation + edge proxy behaviors and flags. |
| internal/metalman/commands/controller.go | Adds metalman controller role command entrypoint. |
| internal/metalman/attestation/attestation.go | Adds AttestMachine helper to avoid source-IP identity in session flow. |
| internal/metalman/attestation/attestation_test.go | Tests AttestMachine does not resolve by request source IP. |
| images/netboot/assets/vendor-data.tmpl | Switches to session-scoped callback URLs in cloud-init reporting. |
| images/netboot/assets/init | Uses boot-image-written URL parameter and posts completion milestone. |
| images/netboot/assets/grub.cfg.tmpl | Uses artifact base URL and embeds boot-image-written callback URL. |
| hack/smoke-metalman-http.py | Updates HTTP smoke suite to split roles + session capability URLs + bootstrap-netboot. |
| hack/smoke_metalman_contract_test.go | Ensures smoke suites use split runtime and capability entrypoint patterns. |
| hack/metalman-redfish-fixture.py | Removes reliance on local Metalman cache; fetches capability entrypoint. |
| e2e/operator/reaper_e2e_test.go | Updates e2e expectations to confirm removed Metalman DHCP flag isn’t retained. |
| docs/content/reference/machina-crd.md | Documents new netboot axes + NetbootEndpoint/NetbootSession resources. |
| docs/content/reference/cli.md | Documents kubectl unbounded site bootstrap-netboot. |
| docs/content/reference/architecture.md | Updates architecture docs for split Metalman roles and session model. |
| docs/content/reference/agent/configuration.md | Updates attestation URL semantics to capability-scoped session URL. |
| docs/content/concepts/bare-metal.md | Updates conceptual docs for endpoint/session based netboot flows. |
| designs/metalman-netboot-architecture.md | Adds detailed design document for netboot architecture. |
| deploy/unbounded-operator/02-rbac.yaml.tmpl | Expands operator RBAC for netboot endpoints and PDB reconciliation. |
| deploy/net/node/daemonset_test.go | Adds test ensuring net-node DaemonSet excludes synthetic external nodes. |
| deploy/net/node/03-daemonset.yaml.tmpl | Excludes synthetic external nodes via nodeAffinity. |
| deploy/machina/crd/unbounded-cloud.io_sites.yaml | Removes deprecated Metalman component fields from Site CRD. |
| deploy/machina/crd/unbounded-cloud.io_netbootendpoints.yaml | Adds NetbootEndpoint CRD. |
| deploy/machina/crd/unbounded-cloud.io_machines.yaml | Replaces deprecated bootProtocol with transport/config/networkMode/endpointRef. |
| deploy/machina/crd/unbounded-cloud.io_machineoperations.yaml | Adds NetbootSessionRef to operation target input schema. |
| deploy/machina/06-metalman-rbac.yaml.tmpl | Splits RBAC for controller/server/edge service accounts and permissions. |
| cmd/metalman/main.go | Switches CLI to expose controller/server/edge subcommands (drops serve-pxe). |
| cmd/kubectl-unbounded/app/machine_ops.go | Adds net API to kubectl scheme for new bootstrap flows. |
| cmd/kubectl-unbounded/app/cmd_site.go | Adds site bootstrap-netboot command to CLI. |
| api/machina/v1alpha3/site_types.go | Removes deprecated Metalman component fields from API type. |
| api/machina/v1alpha3/site_types_test.go | Adds schema test to ensure only Metalman enablement is exposed. |
| api/machina/v1alpha3/netbootsession_types.go | Adds NetbootSession API type and schema annotations. |
| api/machina/v1alpha3/netbootendpoint_types.go | Adds NetbootEndpoint API type and schema annotations. |
| api/machina/v1alpha3/netboot_validation_test.go | Adds CRD schema validation tests for endpoint/session and session-ref fields. |
| api/machina/v1alpha3/machineoperation_types.go | Adds NetbootSessionRef field to MachineOperation target input. |
| api/machina/v1alpha3/machine_validation_test.go | Adds schema test ensuring netboot axes exist and bootProtocol removed. |
| api/machina/v1alpha3/machine_types.go | Implements netboot axes (transport/configurationSource/networkMode/endpointRef) and helpers. |
Files not reviewed (1)
- api/machina/v1alpha3/zz_generated.deepcopy.go: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+154
to
+157
| func validSessionArtifactPath(filename string) bool { | ||
| parts := strings.Split(filename, "/") | ||
| return len(parts) >= 7 && parts[0] == "v1" && parts[1] == "netboot" && parts[2] == "sessions" && parts[3] != "" && parts[4] != "" && parts[5] == "artifacts" && parts[6] != "" | ||
| } |
Comment on lines
+42
to
+49
| prefix := "system:serviceaccount:" | ||
| if !strings.HasPrefix(review.Status.User.Username, prefix) { | ||
| return false | ||
| } | ||
|
|
||
| parts := strings.Split(strings.TrimPrefix(review.Status.User.Username, prefix), ":") | ||
|
|
||
| return len(parts) == 2 && parts[1] == a.ServiceAccountName |
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.