Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions dag/extdeps/os/ubuntu_autoinstall.dag
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module extdeps.os.ubuntu_autoinstall

import std.logic { Bool }
import std.types { Int, NonEmptyStr }
import std.types { Int, NonEmptyStr, Bool }
import std.os.types { UbuntuDistribution }
import extdeps.uri { Uri, Https }
import extdeps.external_authority { ExternalAuthority }
Expand All @@ -24,6 +23,10 @@ type AutoinstallIdentity {
hashed_password: NonEmptyStr
}

type AutoinstallStoragePolicy
= StoragePolicyAbsent
| StoragePolicyDirectLayout

type UbuntuAutoinstallPayload {
autoinstall_version: Int
delivery: AutoinstallDeliveryMethod
Expand All @@ -33,4 +36,5 @@ type UbuntuAutoinstallPayload {
locale: NonEmptyStr
keyboard_layout: NonEmptyStr
install_openssh_server: Bool
storage_policy: AutoinstallStoragePolicy
}
5 changes: 5 additions & 0 deletions dag/gunbc/os_install.dag
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import extdeps.os.ubuntu_autoinstall {
AutoinstallIdentity,
NoCloudNet,
NoCloudLocal,
AutoinstallStoragePolicy,
StoragePolicyAbsent,
StoragePolicyDirectLayout,
}
import gunbc.fleet_intent_network { operator_host_srv3, operator_lan_segment }
import product.placement_supply { HostIdentity }
Expand Down Expand Up @@ -130,6 +133,7 @@ data srv3_ubuntu_autoinstall: UbuntuAutoinstallPayload = UbuntuAutoinstallPayloa
locale: "en_US.UTF-8",
keyboard_layout: "us",
install_openssh_server: true,
storage_policy: StoragePolicyAbsent,
}

data srv3_ubuntu_autoinstall_on_iso: UbuntuAutoinstallPayload = UbuntuAutoinstallPayload {
Expand All @@ -141,6 +145,7 @@ data srv3_ubuntu_autoinstall_on_iso: UbuntuAutoinstallPayload = UbuntuAutoinstal
locale: "en_US.UTF-8",
keyboard_layout: "us",
install_openssh_server: true,
storage_policy: StoragePolicyAbsent,
}

data srv3_os_install_plan: Srv3OsInstallPlan = Srv3OsInstallPlan {
Expand Down
117 changes: 117 additions & 0 deletions dag/gunbc/os_install_deduction.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
module gunbc.os_install_deduction

import std.types { String, NonEmptyStr, Timestamp, Bool }
import extdeps.os.ubuntu_autoinstall {
UbuntuAutoinstallPayload,
AutoinstallStoragePolicy,
StoragePolicyAbsent,
StoragePolicyDirectLayout,
NoCloudLocal,
NoCloudNet,
}
import product.placement_supply { HostIdentity }

data os_install_deduction_doc: String = "OS install deduction spine — construction-time preflight (intent+policy completeness) and runtime KVM-attested diagnostic vocabulary (T1 only; not wired to srv3_os_install_diagnostic fold until srv3-install-reconcile-a). Preflight fold is scoped to the NBD-proxy/on-ISO actuator path: NoCloudNet is incomplete for that path only, not universally. Not a monitoring product (roadmap 2-os-install-deduction-a). Deduction half pairs with std.temporal_effect receipt/resume half."

type TargetDiskState
= EmptyDisk
| ForeignOsPresent
| UnknownDiskState

type OsInstallPreflightVerdict
= CompleteForUnattended
| NotUnattendedByPolicy
| RequiresStoragePolicy
| RequiresDiskObservation
| IncompleteSeedDelivery
| AutoinstallIncompleteNotBootable

type OsInstallPreflightPlan
= PreflightNoop
| RemasterWithStoragePolicy
| RefuseUntilStoragePolicyDeclared
| RefuseNeedsDiskObservation
| RefuseIncompleteSeedDelivery
| RefuseNotUnattendedByPolicy

type OsInstallRuntimeDiagnosticVerdict
= ReadyToBoot
| KvmFirmwareIdleObserved
| BootOverrideConsumedNoInstallEvidence
| InstallerAwaitingStorage
| InstallerRunning
| InstallerHung
| KvmSuggestsOsBooted
| OsInstalled

type KvmObservedScreen
= FirmwareSetup
| UefiBootMenu
| GrubMenu
| SubiquityStorageScreen
| SubiquityInstalling
| LoginPrompt
| ErrorScreen { summary: NonEmptyStr }

type KvmOperatorAttestation {
target: HostIdentity
observed_screen: KvmObservedScreen
observed_at: Timestamp
attested_by: NonEmptyStr
}

fn fold_nbd_proxy_os_install_preflight_verdict(
payload: UbuntuAutoinstallPayload,
disk: TargetDiskState,
) -> OsInstallPreflightVerdict {
if !payload.fully_automated {
NotUnattendedByPolicy
} else {
match payload.delivery {
NoCloudNet { seed_url: _ } => IncompleteSeedDelivery
NoCloudLocal =>
match payload.storage_policy {
StoragePolicyDirectLayout => CompleteForUnattended
StoragePolicyAbsent =>
match disk {
EmptyDisk => RequiresStoragePolicy
ForeignOsPresent => AutoinstallIncompleteNotBootable
UnknownDiskState => RequiresDiskObservation
}
}
}
}
}

fn plan_for_os_install_preflight_verdict(
verdict: OsInstallPreflightVerdict,
) -> OsInstallPreflightPlan {
match verdict {
CompleteForUnattended => PreflightNoop
NotUnattendedByPolicy => RefuseNotUnattendedByPolicy
RequiresStoragePolicy => RemasterWithStoragePolicy
RequiresDiskObservation => RefuseNeedsDiskObservation
IncompleteSeedDelivery => RefuseIncompleteSeedDelivery
AutoinstallIncompleteNotBootable => RefuseUntilStoragePolicyDeclared
}
}

fn runtime_verdict_from_kvm_attestation(
attestation: KvmOperatorAttestation,
preflight: OsInstallPreflightVerdict,
) -> OsInstallRuntimeDiagnosticVerdict {
match attestation.observed_screen {
SubiquityStorageScreen =>
match preflight {
AutoinstallIncompleteNotBootable => InstallerAwaitingStorage
RequiresStoragePolicy => InstallerAwaitingStorage
_ => InstallerRunning
}
SubiquityInstalling => InstallerRunning
LoginPrompt => KvmSuggestsOsBooted
FirmwareSetup => KvmFirmwareIdleObserved
UefiBootMenu => KvmFirmwareIdleObserved
GrubMenu => InstallerRunning
ErrorScreen { summary: _ } => InstallerHung
}
}
15 changes: 14 additions & 1 deletion dag/gunbc/os_install_emit.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import std.types { List, String }
import extdeps.os.ubuntu_autoinstall {
UbuntuAutoinstallPayload,
AutoinstallIdentity,
AutoinstallStoragePolicy,
StoragePolicyAbsent,
StoragePolicyDirectLayout,
}
import extdeps.languages.yaml.types {
YamlValue, YamlKeyValue,
Expand Down Expand Up @@ -41,9 +44,19 @@ fn autoinstall_inner_entries(payload: UbuntuAutoinstallPayload) -> List<YamlKeyV
base
}
if payload.fully_automated {
append(with_ssh, items: [
let automated = append(with_ssh, items: [
kv(key: "interactive-sections", value: yaml_sequence(elements: empty_yaml_values)),
])
match payload.storage_policy {
StoragePolicyAbsent => automated
StoragePolicyDirectLayout => append(automated, items: [
kv(key: "storage", value: yaml_mapping(entries: [
kv(key: "layout", value: yaml_mapping(entries: [
kv(key: "name", value: yaml_string(s: "direct")),
])),
])),
])
}
} else {
with_ssh
}
Expand Down
8 changes: 8 additions & 0 deletions dag/gunbc/roadmap_authority.dag
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ fn section_2() -> RoadmapSection {
authored_doc(id: "6-shell-slice1", done: false, content: "**slice 1 — control-flow emit** — `If` then `For`/`While` (`orch_emit_step` arms + byte goldens)", path: "docs/plans/shell-emission-model.md"),
authored_doc(id: "6-shell-slice2", done: false, content: "**slice 2 — fleet_converge emit** — `fleet_converge_emit` → committed `.github/fleet-converge.sh`; the emit half of the re-land", path: "docs/plans/shell-emission-model.md"),
authored_doc(id: "2-host-effect-phases", done: false, content: "**`apply()` Phases B–F** — B `host_exec`→`apply()` (gated on srv3 OsInstalled) · C Redfish live (partially via #6097) · D converge lane = EmitArtifactThenThinRun handler (first ctrl LOC deleted) · E pull-mode self-converge (autoinstall plants the on-host agent; the push star retires) · F decom. Phase A landed (#5756).", path: "docs/plans/host-effect-orchestration.md"),
owned(rn: authored_wi(id: "2-temporal-effect-spine-a", done: false, content: "**temporal-effect-spine-a — temporal realization spine (T1 vocabulary)** *(operator 2026-07-02; not a workflow engine)* — `std.temporal_effect`: durable facts + `plan_next_step_from_prior_receipt_and_lease` (single prior+lease; list fold is consumer-side); 🟡 markers on stringly receipt labels + derived step id. RED: approval/lease/read-back gates. **Non-goals:** live mutation, DB, scheduler. **Accept (T1):** witness suite green.", intricacy: IntricacyHigh, volume: VolumeSmall, repo: "gunbc"), owner: "dispatched 2026-07-02 · zesty-bat-588"),
owned(rn: authored_wi(id: "2-os-install-deduction-a", done: false, content: "**os-install-deduction-a — preflight + KVM diagnostic vocabulary (T1)** *(operator 2026-07-02; deduction half; NOT wired to srv3_os_install_diagnostic until reconcile-a)* — `gunbc.os_install_deduction`: `fold_nbd_proxy_os_install_preflight_verdict` (NBD-proxy/on-ISO actuator scope — NoCloudNet incomplete for this path only), storage policy on payload, `TargetDiskState`, weak KVM verdicts (`KvmFirmwareIdleObserved`, `KvmSuggestsOsBooted`; `OsInstalled` reserved for router read-back). RED: remove storage flips ReadyToBoot; KVM login ≠ OsInstalled. **Non-goals:** live mutation, monitoring product, DB. **Accept (T1):** witness suite green.", intricacy: IntricacyHigh, volume: VolumeSmall, repo: "gunbc"), owner: "dispatched 2026-07-02 · zesty-bat-588"),
authored_wi(id: "2-srv3-install-reconcile-a", done: false, content: "**srv3-install-reconcile-a — dry-run reconcile entrypoint** *(queued; gated on temporal-effect-spine-a + os-install-deduction-a)* — `InstallAttemptIntent` + workflow steps as data; `srv3_os_install_reconcile` folds preflight + diagnostic + temporal spine; dry-run first. **Accept (T3):** dry-run receipt on srv1 actuator host.", intricacy: IntricacyHigh, volume: VolumeMedium, repo: "gunbc"),
authored_doc(id: "2-srv3-osinstalled", done: false, content: "**srv3 → OsInstalled** — finish the greenfield install over the solve-driven NBD-proxy actuator (#6097, live BMC); proves the install band end-to-end.", path: "docs/plans/srv3-webui-kvm-virtual-media.md"),
authored_wi(id: "2-resource-namespace-upsert-a", done: false, content: "**resource-namespace-upsert-a — vocabulary only** *(#6134 srv3 bringup follow-up, operator 2026-07-02)* — FileNamespace/ToolNamespace/ProcessNamespace/SecretFileNamespace; shared verdicts Converged|Absent|Stale|Conflict|Inaccessible|UnknownRefused; plans Noop|Create|UpsertAccess|DrainThenStart|Refuse. RED: foreign process on 10809=Conflict not kill; outside-namespace chmod=Refuse; stale seeded ISO ≠ AlreadyPresent. Non-goal: live srv3 mutation.", intricacy: IntricacyHigh, volume: VolumeSmall, repo: "gunbc"),
authored_wi(id: "2-install-media-generic-layer", done: false, content: "**install-media-generic-layer — extract Ubuntu flavor from process** — split `extdeps/os/install_media.dag` generic shapes (fetch/remaster/serve verdicts) from `ubuntu_*` flavor rows; move `.gunbc-content-hash` sidecar + remaster policy to `gunbc/install_media_*`; mandatory before second OS/distro. Post-#6134.", intricacy: IntricacyHigh, volume: VolumeMedium, repo: "gunbc"),
Expand All @@ -210,6 +213,11 @@ fn section_2() -> RoadmapSection {
authored(id: "2-os-install-generic-naming", done: false, content: "**os-install generic naming cleanup** — rename generic behavior tests/modules away from `srv3_*` where testing credential resolution, remaster classification, workflow escalation; keep srv3 only in instance fixtures (`srv3_pre_install_lease_table`, `srv3_seeded_install_media_artifact`). Post-#6134."),
],
edges: [
RoadmapEdge { child: nid(s: "2-temporal-effect-spine-a"), parent: nid(s: "2-host-effect-phases") },
RoadmapEdge { child: nid(s: "2-os-install-deduction-a"), parent: nid(s: "2-host-effect-phases") },
RoadmapEdge { child: nid(s: "2-srv3-install-reconcile-a"), parent: nid(s: "2-temporal-effect-spine-a") },
RoadmapEdge { child: nid(s: "2-srv3-install-reconcile-a"), parent: nid(s: "2-os-install-deduction-a") },
RoadmapEdge { child: nid(s: "2-srv3-install-reconcile-a"), parent: nid(s: "2-srv3-osinstalled") },
RoadmapEdge { child: nid(s: "2-resource-namespace-upsert-a"), parent: nid(s: "2-srv3-osinstalled") },
RoadmapEdge { child: nid(s: "2-install-media-generic-layer"), parent: nid(s: "2-srv3-osinstalled") },
RoadmapEdge { child: nid(s: "2-nbd-serve-held-session-lease"), parent: nid(s: "2-srv3-osinstalled") },
Expand Down
Loading
Loading