Compare commits
5 Commits
006ffee615
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a1a6c3b81 | |||
| cb9e7332f4 | |||
| db4d5bdf4c | |||
| 0e8b30434f | |||
| f41a916f45 |
@@ -1,6 +1,6 @@
|
||||
# Fruix differences for Guix sysadmins
|
||||
|
||||
Date: 2026-04-05
|
||||
Date: 2026-04-06
|
||||
|
||||
This document is aimed at operators who already know Guix well and want a quick map of where Fruix behaves similarly and where it intentionally differs.
|
||||
|
||||
@@ -171,8 +171,10 @@ So compared with Guix-on-Linux intuition, Fruix operators should be more explici
|
||||
|
||||
This remains the biggest operational gap, but it is no longer a complete gap.
|
||||
|
||||
Installed Fruix systems now provide a small in-guest helper:
|
||||
Installed Fruix systems now provide a larger in-guest helper surface:
|
||||
|
||||
- `fruix system build`
|
||||
- `fruix system reconfigure`
|
||||
- `fruix system status`
|
||||
- `fruix system switch /frx/store/...-fruix-system-...`
|
||||
- `fruix system rollback`
|
||||
@@ -183,11 +185,14 @@ What this gives you today:
|
||||
- explicit rollback-generation tracking
|
||||
- in-place switching between already-staged closures on the installed target
|
||||
- rollback without reinstalling the whole system image again
|
||||
- a validated in-node build path that can read the embedded current declaration inputs
|
||||
- a validated in-node `reconfigure` path that can build a candidate closure locally and stage it as the next generation
|
||||
|
||||
What it still does **not** give you yet compared with Guix:
|
||||
|
||||
- a mature `reconfigure`-style workflow that builds and stages the new closure from inside the target system
|
||||
- a mature end-to-end `upgrade` story for advancing declared inputs automatically
|
||||
- automatic closure transfer/fetch as part of `switch`
|
||||
- a higher-level `deploy` workflow across multiple machines or targets
|
||||
- the broader generation-management UX Guix operators expect
|
||||
|
||||
So if you come from Guix, assume that Fruix now has:
|
||||
@@ -195,7 +200,8 @@ So if you come from Guix, assume that Fruix now has:
|
||||
- strong closure/store semantics
|
||||
- explicit install artifacts
|
||||
- explicit generation metadata roots
|
||||
- a real but still modest installed-system switch/rollback UX
|
||||
- a real installed-system build/reconfigure/switch/rollback surface
|
||||
- but not yet the fuller long-term node/deployment UX that Guix users may expect
|
||||
|
||||
## 7. Fruix keeps Guix-like store semantics, but not Guix/Nix hash-prefix machinery exactly
|
||||
|
||||
@@ -242,37 +248,45 @@ For Guix-familiar operators, the practical takeaway is:
|
||||
- do **not** assume Fruix store prefixes are byte-for-byte comparable to Guix/Nix ones
|
||||
- expect Fruix to prefer a simpler, centralized naming policy unless exact Guix/Nix behavior becomes necessary later
|
||||
|
||||
## 8. Fruix can expose a separate in-system development profile overlay
|
||||
## 8. Fruix can expose separate in-system development and build overlays
|
||||
|
||||
For the validated Phase 20.1 path, Fruix can now expose development tooling separately from the main runtime profile.
|
||||
For the validated Phase 20 path, Fruix now distinguishes three layers instead of two:
|
||||
|
||||
- runtime profile
|
||||
- development profile
|
||||
- build profile
|
||||
|
||||
On those systems, Fruix exposes:
|
||||
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
- development:
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- build:
|
||||
- `/run/current-system/build-profile`
|
||||
- `/run/current-build`
|
||||
- `/usr/local/bin/fruix-build-environment`
|
||||
- canonical base-build compatibility links:
|
||||
- `/usr/include -> /run/current-system/build-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/build-profile/usr/share/mk`
|
||||
|
||||
The intent is:
|
||||
|
||||
- keep the main runtime profile lean
|
||||
- expose headers, `usr/share/mk`, and selected toolchain commands explicitly
|
||||
- satisfy native FreeBSD buildworld/buildkernel expectations for canonical system paths when development support is enabled
|
||||
- avoid treating a development-heavy system image as the default runtime shape
|
||||
- keep the development helper interactive and convenient
|
||||
- keep the build helper narrower, more sanitized, and closer to the actual `buildworld` / `buildkernel` contract
|
||||
- avoid treating a development-heavy or build-heavy image as the default runtime shape
|
||||
|
||||
Compared with Guix, this is conceptually similar to keeping development-oriented state separate from the main runtime identity, but Fruix currently expresses it as a system-attached development overlay rather than through Guix's broader profile/tooling model.
|
||||
Compared with Guix, this is conceptually similar to keeping development-oriented and build-oriented state separate from the main runtime identity, but Fruix currently expresses it as system-attached overlays rather than through Guix's broader profile/tooling model.
|
||||
|
||||
Fruix now also has a narrow guest self-hosted native-build prototype helper at:
|
||||
Fruix still has the guest self-hosted native-build prototype helper at:
|
||||
|
||||
- `/usr/local/bin/fruix-self-hosted-native-build`
|
||||
|
||||
That helper does **not** just reuse the whole exported development shell wholesale. The validated prototype had to sanitize development-oriented variables such as `MAKEFLAGS`, `CPPFLAGS`, `CFLAGS`, `CXXFLAGS`, and `LDFLAGS` before `buildworld`, because those are convenient for smaller development tasks but can poison the FreeBSD world/kernel bootstrap path.
|
||||
|
||||
The practical Fruix takeaway is:
|
||||
But that helper now explicitly uses the build helper contract instead of trying to reuse the full interactive development shell. The practical Fruix takeaway is:
|
||||
|
||||
- the development overlay makes native base work possible inside the system
|
||||
- but real guest self-hosted base builds still need their own stricter build contract
|
||||
- the build overlay gives Fruix a stricter, more reproducible contract for real base builds
|
||||
|
||||
Fruix now also makes an explicit distinction between:
|
||||
|
||||
@@ -294,6 +308,32 @@ Compared with Guix, this is a more explicit split between:
|
||||
- a mutable result/staging area for native build execution
|
||||
- and the immutable store identities that Fruix treats as the real promoted result
|
||||
|
||||
Fruix also now models native-build placement more explicitly as an executor choice.
|
||||
|
||||
Current executor kinds are:
|
||||
|
||||
- `host`
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
|
||||
So instead of treating:
|
||||
|
||||
- host-driven builds
|
||||
- host-initiated guest builds
|
||||
- guest self-hosted builds
|
||||
|
||||
as three unrelated architectural forks, Fruix is moving toward one native-build result model with different executor policies attached to it.
|
||||
|
||||
Fruix also now lets system declarations consume a promoted native-build result bundle directly.
|
||||
|
||||
That means Fruix can now distinguish more explicitly between:
|
||||
|
||||
- a mutable build/result root used during execution
|
||||
- an immutable promoted native-build identity in `/frx/store`
|
||||
- and a later system declaration that points at that promoted identity as an input
|
||||
|
||||
Compared with Guix, this is still Guix-like in the important sense that the deployed system is identified by immutable store objects, but Fruix is making the FreeBSD native-base result set itself a more explicit first-class declaration input than it was before.
|
||||
|
||||
## Where Fruix is intentionally trying to improve on Guix's representation
|
||||
|
||||
Fruix is not trying to improve on Guix's core semantics. Guix already got those right.
|
||||
|
||||
139
docs/PROGRESS.md
139
docs/PROGRESS.md
@@ -38,6 +38,12 @@ Fruix currently has:
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- a validated separate in-system build environment overlay via:
|
||||
- `/run/current-system/build-profile`
|
||||
- `/run/current-build`
|
||||
- `/usr/local/bin/fruix-build-environment`
|
||||
- `/usr/include -> /run/current-system/build-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/build-profile/usr/share/mk`
|
||||
- a validated host-initiated native base-build path inside a Fruix-managed guest via:
|
||||
- real XCP-ng boot of a development-enabled Fruix system
|
||||
- in-guest `buildworld` / `buildkernel`
|
||||
@@ -53,6 +59,22 @@ Fruix currently has:
|
||||
- `/frx/store/...-fruix-native-headers-...`
|
||||
- `/frx/store/...-fruix-native-bootloader-...`
|
||||
- `/frx/store/...-fruix-native-build-result-...`
|
||||
- an explicit executor model for native base builds with current executor kinds:
|
||||
- `host`
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
- end-to-end validated staged-result-plus-promotion paths for executor policies:
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
- system declarations that can now consume a promoted native-build result bundle directly via:
|
||||
- `promoted-native-build-result`
|
||||
- `operating-system-from-promoted-native-build-result`
|
||||
- a real XCP-ng boot validation of a system materialized from a promoted native-build result identity
|
||||
- installed systems that now carry their own canonical declaration inputs and bundled Fruix node CLI sources
|
||||
- a real XCP-ng validation of in-node:
|
||||
- `fruix system build`
|
||||
- `fruix system reconfigure`
|
||||
- `fruix system rollback`
|
||||
|
||||
Validated boot modes still are:
|
||||
|
||||
@@ -65,48 +87,98 @@ The validated Phase 18 installation work currently uses:
|
||||
|
||||
## Latest completed achievement
|
||||
|
||||
### 2026-04-05 — Native base builds promoted into first-class Fruix store objects
|
||||
### 2026-04-06 — Fruix now separates interactive development from strict native base-build environment
|
||||
|
||||
Fruix now has a validated end-to-end path that treats guest native base-build results as **staged mutable results first**, and then promotes them into **immutable Fruix store identities**.
|
||||
Fruix now has a more explicit three-layer model for build-capable FreeBSD systems:
|
||||
|
||||
- runtime profile
|
||||
- development profile
|
||||
- build profile
|
||||
|
||||
Highlights:
|
||||
|
||||
- guest self-hosted runs still record staged results under:
|
||||
- `/var/lib/fruix/native-builds/<run-id>`
|
||||
- `/var/lib/fruix/native-builds/latest`
|
||||
- those result roots now carry promotion metadata describing:
|
||||
- executor / executor-version
|
||||
- closure path
|
||||
- source store provenance
|
||||
- build policy
|
||||
- artifact entries for:
|
||||
- `world`
|
||||
- `kernel`
|
||||
- `headers`
|
||||
- `bootloader`
|
||||
- the host can now run:
|
||||
- `fruix native-build promote RESULT_ROOT`
|
||||
- promotion creates immutable `/frx/store` objects for:
|
||||
- `world`
|
||||
- `kernel`
|
||||
- `headers`
|
||||
- `bootloader`
|
||||
- promotion also creates a result-bundle store object that references those artifact stores
|
||||
- the validated promotion metadata now makes Fruix-native native-build identity explicit instead of leaving results only as ad hoc files under `/var/lib/fruix/native-builds/...`
|
||||
- `<operating-system>` now supports separate `build-packages`
|
||||
- system closures can now materialize both:
|
||||
- `development-profile`
|
||||
- `build-profile`
|
||||
- build-capable systems now expose:
|
||||
- `/run/current-system/build-profile`
|
||||
- `/run/current-build`
|
||||
- `/usr/local/bin/fruix-build-environment`
|
||||
- canonical compatibility links for native base builds now come from the build profile:
|
||||
- `/usr/include -> /run/current-system/build-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/build-profile/usr/share/mk`
|
||||
- the new build helper intentionally clears development-shell variables such as:
|
||||
- `MAKEFLAGS`
|
||||
- `CPPFLAGS`
|
||||
- `CFLAGS`
|
||||
- `CXXFLAGS`
|
||||
- `LDFLAGS`
|
||||
- the self-hosted native-build helper now uses this stricter build-helper contract instead of manually reconstructing that sanitization ad hoc
|
||||
- promotion metadata for native-build results now records `build-profile` explicitly
|
||||
|
||||
Validation:
|
||||
|
||||
- `PASS phase20-development-environment-xcpng`
|
||||
- `PASS phase20-self-hosted-native-build-xcpng`
|
||||
- `PASS phase20-native-build-store-promotion-xcpng`
|
||||
- `PASS phase20-host-initiated-native-build-xcpng`
|
||||
- `PASS phase20-host-initiated-native-build-store-promotion-xcpng`
|
||||
|
||||
Representative validated metadata included:
|
||||
|
||||
- `build_profile_guest=/run/current-system/build-profile`
|
||||
- `build_profile=/run/current-system/build-profile`
|
||||
- `helper_version=5`
|
||||
- `executor_version=5`
|
||||
|
||||
Report:
|
||||
|
||||
- `docs/reports/postphase20-build-profile-separation-freebsd.md`
|
||||
- `docs/system-deployment-workflow.md`
|
||||
- `docs/GUIX_DIFFERENCES.md`
|
||||
|
||||
### 2026-04-06 — Installed systems can now build and reconfigure themselves from local declaration state
|
||||
|
||||
Fruix-installed systems are now meaningfully closer to real Fruix nodes.
|
||||
|
||||
Highlights:
|
||||
|
||||
- system closures now carry canonical declaration metadata in:
|
||||
- `metadata/system-declaration.scm`
|
||||
- `metadata/system-declaration-info.scm`
|
||||
- `metadata/system-declaration-system`
|
||||
- system closures now also carry bundled Fruix node CLI sources in:
|
||||
- `share/fruix/node/scripts/fruix.scm`
|
||||
- `share/fruix/node/modules/...`
|
||||
- `share/fruix/node/guix/guix/build/utils.scm`
|
||||
- the installed helper at `/usr/local/bin/fruix` now supports:
|
||||
- `fruix system build`
|
||||
- `fruix system reconfigure`
|
||||
- `fruix system status`
|
||||
- `fruix system switch`
|
||||
- `fruix system rollback`
|
||||
- no-argument in-node `build` and `reconfigure` now use the node's own embedded declaration inputs
|
||||
- in-node Fruix builds now reuse the installed Guile/Shepherd runtime stores already referenced by the system instead of assuming host-only `/tmp/...` build prefixes
|
||||
- the real XCP-ng validation proved the full installed-node flow:
|
||||
- boot current system
|
||||
- build from local declaration state
|
||||
- build a candidate declaration on-node
|
||||
- `reconfigure` into that candidate generation
|
||||
- reboot into the candidate generation
|
||||
- `rollback`
|
||||
- reboot back into the original generation
|
||||
|
||||
Validation:
|
||||
|
||||
- `PASS postphase20-installed-node-build-reconfigure-xcpng`
|
||||
|
||||
Reports:
|
||||
|
||||
- `docs/reports/postphase20-promoted-native-base-declarations-freebsd.md`
|
||||
- `docs/reports/postphase20-installed-node-management-freebsd.md`
|
||||
- `docs/system-deployment-workflow.md`
|
||||
- `docs/GUIX_DIFFERENCES.md`
|
||||
- `docs/reports/phase20-development-environment-freebsd.md`
|
||||
- `docs/reports/phase20-host-initiated-native-builds-freebsd.md`
|
||||
- `docs/reports/phase20-self-hosted-native-builds-freebsd.md`
|
||||
- `docs/reports/phase20-native-build-store-promotion-freebsd.md`
|
||||
|
||||
## Recent major milestones
|
||||
|
||||
@@ -134,12 +206,15 @@ Reports:
|
||||
|
||||
The next practical follow-up is now clearer:
|
||||
|
||||
- unify host-initiated and self-hosted native-build execution behind a shared Fruix executor/result model
|
||||
- make the same first-class promotion story available regardless of whether the outer loop is host-driven or guest-driven
|
||||
- decide how much of result import/promotion should remain host-side versus become a more integrated Fruix deployment action
|
||||
- grow the installed-node command surface from validated `build`/`reconfigure`/`rollback` toward:
|
||||
- `upgrade`
|
||||
- `build-base`
|
||||
- `deploy`
|
||||
- decide how executor policy, native-base promotion, and installed-node reconfiguration should compose in one operator-facing workflow
|
||||
- determine how much of native-build request/promotion should remain explicit versus being absorbed into higher-level Fruix node actions
|
||||
|
||||
The immediate architectural direction is no longer just “can guest self-hosting work?”
|
||||
|
||||
It is now:
|
||||
|
||||
- how should Fruix represent native base builds as real first-class objects and workflows across different executors?
|
||||
- how should Fruix expose real managed-node behavior across declaration inputs, native-base results, generation switching, and deployment actions?
|
||||
|
||||
202
docs/reports/phase20-native-build-executor-model-freebsd.md
Normal file
202
docs/reports/phase20-native-build-executor-model-freebsd.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Post-Phase 20: native build executor model
|
||||
|
||||
Date: 2026-04-06
|
||||
|
||||
## Goal
|
||||
|
||||
Turn the now-proven native base-build placement options into one Fruix abstraction instead of treating them as unrelated paths.
|
||||
|
||||
The desired model is:
|
||||
|
||||
- same declared source identity
|
||||
- same expected artifact kinds
|
||||
- same staged-result shape
|
||||
- same promotion/provenance shape
|
||||
- different executor policy
|
||||
|
||||
So the question becomes:
|
||||
|
||||
- where should the build run?
|
||||
|
||||
and the answer is expressed as executor policy rather than as a separate architecture each time.
|
||||
|
||||
## Executor model
|
||||
|
||||
Fruix now has an explicit native-build executor model with current executor kinds:
|
||||
|
||||
- `host`
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
|
||||
and intended future extension points:
|
||||
|
||||
- `jail`
|
||||
- `remote-builder`
|
||||
|
||||
The new executor model is implemented in:
|
||||
|
||||
- `modules/fruix/system/freebsd/executor.scm`
|
||||
|
||||
It defines a structured executor object that records at least:
|
||||
|
||||
- `kind`
|
||||
- `name`
|
||||
- `version`
|
||||
- `properties`
|
||||
|
||||
## What changed
|
||||
|
||||
### 1. Structured executor metadata
|
||||
|
||||
Native-build result metadata is no longer limited to a flat string such as:
|
||||
|
||||
- `guest-self-hosted`
|
||||
|
||||
Instead, result/promotion objects now carry a structured executor description.
|
||||
|
||||
Representative executor objects now look like:
|
||||
|
||||
```scheme
|
||||
((kind . self-hosted)
|
||||
(name . "guest-self-hosted")
|
||||
(version . "4")
|
||||
(properties . (...)))
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```scheme
|
||||
((kind . ssh-guest)
|
||||
(name . "ssh-guest")
|
||||
(version . "1")
|
||||
(properties . (...)))
|
||||
```
|
||||
|
||||
Promoted store metadata also now records compatibility fields derived from that executor object:
|
||||
|
||||
- `executor-kind`
|
||||
- `executor-name`
|
||||
- `executor-version`
|
||||
|
||||
### 2. Shared staged-result shape across executors
|
||||
|
||||
Both validated executor paths now converge on the same mutable staging layout under:
|
||||
|
||||
- `/var/lib/fruix/native-builds/<run-id>`
|
||||
|
||||
with promoted artifacts staged under:
|
||||
|
||||
- `artifacts/world`
|
||||
- `artifacts/kernel`
|
||||
- `artifacts/headers`
|
||||
- `artifacts/bootloader`
|
||||
|
||||
and promotion metadata recorded in:
|
||||
|
||||
- `promotion.scm`
|
||||
|
||||
The heavy build work remains executor-specific, but the result shape is now shared.
|
||||
|
||||
### 3. Shared immutable promotion path
|
||||
|
||||
Both validated executor paths now promote through the same command:
|
||||
|
||||
```sh
|
||||
fruix native-build promote RESULT_ROOT
|
||||
```
|
||||
|
||||
That promotion creates immutable store identities for:
|
||||
|
||||
- `world`
|
||||
- `kernel`
|
||||
- `headers`
|
||||
- `bootloader`
|
||||
- result bundle
|
||||
|
||||
under `/frx/store/...`.
|
||||
|
||||
## Validated executor policies
|
||||
|
||||
### `self-hosted`
|
||||
|
||||
The self-hosted guest helper now emits the structured executor metadata directly from:
|
||||
|
||||
- `/usr/local/bin/fruix-self-hosted-native-build`
|
||||
|
||||
Validated self-hosted promotion flow:
|
||||
|
||||
- `PASS phase20-self-hosted-native-build-xcpng`
|
||||
- `PASS phase20-native-build-store-promotion-xcpng`
|
||||
|
||||
Representative promoted result:
|
||||
|
||||
```text
|
||||
result_store=/frx/store/0423193b9bd5e652bdb9d94d077e40dfcc3e9e78-fruix-native-build-result-15.0-STABLE-guest-self-hosted
|
||||
world_store=/frx/store/5f67e95058186147206ff6f5da2243a09212e358-fruix-native-world-15.0-STABLE-guest-self-hosted
|
||||
kernel_store=/frx/store/3a32797cc187a90e8273f205eababae6246568d9-fruix-native-kernel-15.0-STABLE-guest-self-hosted
|
||||
headers_store=/frx/store/1d54d9814461f003e91add8cd37e94ac5f3d04ce-fruix-native-headers-15.0-STABLE-guest-self-hosted
|
||||
bootloader_store=/frx/store/49f4885f0f05a324ac826f2618d4c7a923ca30d2-fruix-native-bootloader-15.0-STABLE-guest-self-hosted
|
||||
```
|
||||
|
||||
### `ssh-guest`
|
||||
|
||||
The host-initiated guest path now also stages a shared native-build result root under:
|
||||
|
||||
- `/var/lib/fruix/native-builds/<run-id>`
|
||||
|
||||
instead of stopping at temporary build directories alone.
|
||||
|
||||
Its promotion metadata records executor policy as:
|
||||
|
||||
- `kind = ssh-guest`
|
||||
- `name = ssh-guest`
|
||||
- `version = 1`
|
||||
|
||||
with executor properties including:
|
||||
|
||||
- `transport = ssh`
|
||||
- `orchestrator = host`
|
||||
- guest addressing / VM identity metadata
|
||||
|
||||
Validated host-initiated promotion flow:
|
||||
|
||||
- `PASS phase20-host-initiated-native-build-xcpng`
|
||||
- `PASS phase20-host-initiated-native-build-store-promotion-xcpng`
|
||||
|
||||
Representative promoted result:
|
||||
|
||||
```text
|
||||
result_store=/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest
|
||||
world_store=/frx/store/89c7a71c3df148a1f99b13d57fd6be88243eb2cb-fruix-native-world-15.0-STABLE-ssh-guest
|
||||
kernel_store=/frx/store/93bac81122022b40438d356146a6854b4ee48513-fruix-native-kernel-15.0-STABLE-ssh-guest
|
||||
headers_store=/frx/store/dd7f39f526bca4849caf1eaf96ae25d29b43493c-fruix-native-headers-15.0-STABLE-ssh-guest
|
||||
bootloader_store=/frx/store/78b1c6b0b5c0c2c1549f5f42f3d64b6d9293669b-fruix-native-bootloader-15.0-STABLE-ssh-guest
|
||||
```
|
||||
|
||||
## Important result
|
||||
|
||||
The same declared source and artifact contract now works across two different executor policies:
|
||||
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
|
||||
while preserving the same Fruix-native staging/promotion split:
|
||||
|
||||
- mutable result roots under `/var/lib/fruix/native-builds/...`
|
||||
- immutable promoted identities under `/frx/store/...`
|
||||
|
||||
That is the core architectural win of the executor model.
|
||||
|
||||
## What is not yet fully unified
|
||||
|
||||
The `host` executor kind now exists in the model, but the fully shared staged-result-plus-promotion workflow is not yet wired through the existing host-local native build path.
|
||||
|
||||
So the executor model is introduced and real-VM validated across two policies, but not yet uniformly productized across every native-build entry point.
|
||||
|
||||
## Result
|
||||
|
||||
Fruix now treats native-build placement as executor policy rather than as an architectural fork.
|
||||
|
||||
That means the next step is no longer to invent another build path from scratch.
|
||||
|
||||
It is to keep extending the same executor/result/promotion model so additional execution policies can plug into the same Fruix-native object story.
|
||||
223
docs/reports/postphase20-build-profile-separation-freebsd.md
Normal file
223
docs/reports/postphase20-build-profile-separation-freebsd.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# Post-Phase 20: separate development from native base-build environment
|
||||
|
||||
Date: 2026-04-06
|
||||
|
||||
## Goal
|
||||
|
||||
Tighten the distinction that Phase 20.3 exposed in practice:
|
||||
|
||||
- an interactive development shell is not the same thing as a reliable native base-build environment
|
||||
|
||||
Fruix now models three layers instead of two:
|
||||
|
||||
- runtime profile
|
||||
- development profile
|
||||
- build profile
|
||||
|
||||
## Why this change was needed
|
||||
|
||||
The earlier self-hosted native-build prototype proved that simply reusing the exported development environment for `buildworld` / `buildkernel` was too loose.
|
||||
|
||||
Development-oriented exports like:
|
||||
|
||||
- `MAKEFLAGS`
|
||||
- `CPPFLAGS`
|
||||
- `CFLAGS`
|
||||
- `CXXFLAGS`
|
||||
- `LDFLAGS`
|
||||
|
||||
are useful for interactive compilation work, but they are the wrong contract for a real FreeBSD world/kernel bootstrap.
|
||||
|
||||
Phase 20.3 previously worked around that by manually sanitizing the shell before running the build.
|
||||
|
||||
This change makes that separation explicit in the product model instead of keeping it as an ad hoc helper detail.
|
||||
|
||||
## Implementation
|
||||
|
||||
### New operating-system layer
|
||||
|
||||
`modules/fruix/system/freebsd/model.scm` now supports:
|
||||
|
||||
- `#:build-packages`
|
||||
- `operating-system-build-packages`
|
||||
|
||||
So a build-capable system can now carry both:
|
||||
|
||||
- `development-packages`
|
||||
- `build-packages`
|
||||
|
||||
separately.
|
||||
|
||||
### New build profile inside the system closure
|
||||
|
||||
When `build-packages` is non-empty, Fruix now materializes:
|
||||
|
||||
- `/frx/store/...-fruix-system-.../build-profile`
|
||||
|
||||
alongside the existing:
|
||||
|
||||
- `/frx/store/...-fruix-system-.../profile`
|
||||
- `/frx/store/...-fruix-system-.../development-profile`
|
||||
|
||||
Store-layout metadata now records both development-package stores and build-package stores explicitly.
|
||||
|
||||
### New in-guest build helper
|
||||
|
||||
Build-capable systems now ship:
|
||||
|
||||
- `/usr/local/bin/fruix-build-environment`
|
||||
|
||||
and expose a stable runtime link:
|
||||
|
||||
- `/run/current-build -> /run/current-system/build-profile`
|
||||
|
||||
That helper intentionally emits a stricter environment contract than the interactive development helper.
|
||||
|
||||
It clears development-shell variables such as:
|
||||
|
||||
- `MAKEOBJDIRPREFIX`
|
||||
- `MAKEFLAGS`
|
||||
- `CC`
|
||||
- `CXX`
|
||||
- `AR`
|
||||
- `RANLIB`
|
||||
- `NM`
|
||||
- `CPPFLAGS`
|
||||
- `CFLAGS`
|
||||
- `CXXFLAGS`
|
||||
- `LDFLAGS`
|
||||
|
||||
and also clears development-helper exports such as:
|
||||
|
||||
- `FRUIX_DEVELOPMENT_PROFILE`
|
||||
- `FRUIX_CC`
|
||||
- `FRUIX_CXX`
|
||||
- `FRUIX_AR`
|
||||
- `FRUIX_RANLIB`
|
||||
- `FRUIX_NM`
|
||||
- `FRUIX_BMAKE`
|
||||
|
||||
Then it exports build-specific values including at least:
|
||||
|
||||
- `FRUIX_BUILD_PROFILE`
|
||||
- `FRUIX_BUILD_INCLUDE`
|
||||
- `FRUIX_BUILD_SHARE_MK`
|
||||
- `FRUIX_BUILD_BIN`
|
||||
- `FRUIX_BUILD_USR_BIN`
|
||||
- `FRUIX_BUILD_CC`
|
||||
- `FRUIX_BUILD_CXX`
|
||||
- `FRUIX_BUILD_AR`
|
||||
- `FRUIX_BUILD_RANLIB`
|
||||
- `FRUIX_BUILD_NM`
|
||||
- `FRUIX_BMAKE`
|
||||
- `PATH`
|
||||
|
||||
Intended use:
|
||||
|
||||
```sh
|
||||
eval "$(/usr/local/bin/fruix-build-environment)"
|
||||
```
|
||||
|
||||
### Canonical build compatibility links now come from the build profile
|
||||
|
||||
For native base-build compatibility, build-capable systems now expose:
|
||||
|
||||
- `/usr/include -> /run/current-system/build-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/build-profile/usr/share/mk`
|
||||
|
||||
This means the running system can still keep development and build content separate while offering the canonical paths that FreeBSD native build machinery expects.
|
||||
|
||||
### Self-hosted native-build helper now uses the build helper contract
|
||||
|
||||
`/usr/local/bin/fruix-self-hosted-native-build` now:
|
||||
|
||||
- requires `build-profile`
|
||||
- requires `/usr/local/bin/fruix-build-environment`
|
||||
- evaluates the build helper contract before `buildworld`
|
||||
- verifies the canonical compatibility links point at `build-profile`
|
||||
|
||||
This replaces the earlier approach where the helper had to reconstruct sanitization manually around a development-oriented environment.
|
||||
|
||||
### Promotion metadata now records build profile provenance
|
||||
|
||||
Promotion metadata emitted for self-hosted native-build results now records:
|
||||
|
||||
- `build-profile`
|
||||
|
||||
Promoted artifact/result metadata also now preserves that field.
|
||||
|
||||
## Validation
|
||||
|
||||
Validated on the approved real XCP-ng path:
|
||||
|
||||
- VM `90490f2e-e8fc-4b7a-388e-5c26f0157289`
|
||||
- VDI `0f1f90d3-48ca-4fa2-91d8-fc6339b95743`
|
||||
|
||||
Passing runs:
|
||||
|
||||
- `PASS phase20-development-environment-xcpng`
|
||||
- `PASS phase20-self-hosted-native-build-xcpng`
|
||||
- `PASS phase20-native-build-store-promotion-xcpng`
|
||||
- `PASS phase20-host-initiated-native-build-xcpng`
|
||||
- `PASS phase20-host-initiated-native-build-store-promotion-xcpng`
|
||||
|
||||
## Representative validated results
|
||||
|
||||
Development/build environment validation:
|
||||
|
||||
```text
|
||||
development_profile_guest=/run/current-system/development-profile
|
||||
build_profile_guest=/run/current-system/build-profile
|
||||
development_env_script=/frx/store/...-fruix-system-.../usr/local/bin/fruix-development-environment
|
||||
build_env_script=/frx/store/...-fruix-system-.../usr/local/bin/fruix-build-environment
|
||||
development_environment=ok
|
||||
```
|
||||
|
||||
Self-hosted native-build validation:
|
||||
|
||||
```text
|
||||
helper_version=5
|
||||
executor_kind=self-hosted
|
||||
executor_name=guest-self-hosted
|
||||
executor_version=5
|
||||
build_profile=/run/current-system/build-profile
|
||||
source_store=/frx/store/12d7704362e95afc2697db63f168b878e082b372-freebsd-source-default
|
||||
self_hosted_native_build=ok
|
||||
```
|
||||
|
||||
Promotion validation:
|
||||
|
||||
```text
|
||||
executor_kind=self-hosted
|
||||
executor_name=guest-self-hosted
|
||||
executor_version=5
|
||||
result_store=/frx/store/3ce6aefd564bc51f2465dcbb5c261355be4c7076-fruix-native-build-result-15.0-STABLE-guest-self-hosted
|
||||
native_build_store_promotion=ok
|
||||
```
|
||||
|
||||
Host-initiated path revalidation with the new build-profile split also succeeded:
|
||||
|
||||
```text
|
||||
executor_kind=ssh-guest
|
||||
executor_name=ssh-guest
|
||||
executor_version=1
|
||||
result_store=/frx/store/93a4837d2588acfde2262010b296df9c7b7b367a-fruix-native-build-result-15.0-STABLE-ssh-guest
|
||||
host_initiated_native_build_store_promotion=ok
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
Fruix now expresses an important product distinction more honestly:
|
||||
|
||||
- development is for interactive work
|
||||
- build is for a stricter native base-build contract
|
||||
|
||||
That reduces special-case cleanup inside the self-hosted helper and gives Fruix a clearer path for future operator-facing commands such as:
|
||||
|
||||
- `fruix system build-base`
|
||||
- `fruix system upgrade`
|
||||
|
||||
because the system model now has an explicit place to say:
|
||||
|
||||
- what is available for interactive development
|
||||
- what is available for real native base builds
|
||||
178
docs/reports/postphase20-installed-node-management-freebsd.md
Normal file
178
docs/reports/postphase20-installed-node-management-freebsd.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# Post-Phase 20: installed systems as real Fruix nodes
|
||||
|
||||
Date: 2026-04-06
|
||||
|
||||
## Goal
|
||||
|
||||
Make a Fruix-installed machine feel like a managed Fruix node instead of only a deployed image with switch/rollback helpers.
|
||||
|
||||
The immediate target was not yet the full long-term command surface of:
|
||||
|
||||
- `fruix system upgrade`
|
||||
- `fruix system build-base`
|
||||
- `fruix system deploy`
|
||||
|
||||
but it was enough to cross an important product threshold:
|
||||
|
||||
- installed nodes can now remember their own declaration inputs
|
||||
- installed nodes can build from those inputs locally
|
||||
- installed nodes can reconfigure themselves into a newly built generation
|
||||
- installed nodes can still roll back cleanly
|
||||
|
||||
## What changed
|
||||
|
||||
### Canonical declaration state now ships inside the system closure
|
||||
|
||||
Fruix system closures now carry explicit declaration metadata:
|
||||
|
||||
- `metadata/system-declaration.scm`
|
||||
- `metadata/system-declaration-info.scm`
|
||||
- `metadata/system-declaration-system`
|
||||
|
||||
That gives an installed system a canonical local answer to:
|
||||
|
||||
- what declaration source produced me?
|
||||
- what top-level system variable should be used?
|
||||
|
||||
This declaration metadata is also recorded through the installed generation layout metadata.
|
||||
|
||||
### Bundled Fruix node CLI sources now ship inside the closure
|
||||
|
||||
Installed system closures now also carry a self-contained Fruix node CLI source bundle under:
|
||||
|
||||
- `share/fruix/node/scripts/fruix.scm`
|
||||
- `share/fruix/node/modules/...`
|
||||
- `share/fruix/node/guix/guix/build/utils.scm`
|
||||
|
||||
This gives the installed node enough local Fruix/Guix Scheme source to run Fruix system actions from the node itself.
|
||||
|
||||
### Installed `fruix` helper gained local build/reconfigure support
|
||||
|
||||
The installed helper at:
|
||||
|
||||
- `/usr/local/bin/fruix`
|
||||
|
||||
now supports:
|
||||
|
||||
- `fruix system build`
|
||||
- `fruix system reconfigure`
|
||||
- `fruix system status`
|
||||
- `fruix system switch`
|
||||
- `fruix system rollback`
|
||||
|
||||
Current behavior:
|
||||
|
||||
- `fruix system build` with no extra arguments uses:
|
||||
- `/run/current-system/metadata/system-declaration.scm`
|
||||
- `/run/current-system/metadata/system-declaration-system`
|
||||
- `fruix system reconfigure` with no extra arguments builds from that same embedded declaration and then stages a switch to the resulting closure
|
||||
- both commands can also take an explicit declaration file plus `--system NAME`, using the same general CLI shape as the host-side Fruix frontend
|
||||
|
||||
### In-node builds now reuse the installed Fruix runtime stores
|
||||
|
||||
A crucial implementation fix was needed here.
|
||||
|
||||
An installed node should not try to reconstruct the Guile/Shepherd runtime prefixes from host-side `/tmp/...` build roots or host `/usr/local/lib/...` assumptions.
|
||||
|
||||
Instead, in-node Fruix builds now explicitly reuse the installed runtime stores already referenced by the current system closure.
|
||||
|
||||
That allows the in-node build path to work on the real installed system rather than depending on build-host-only paths.
|
||||
|
||||
## Validation harness
|
||||
|
||||
Added:
|
||||
|
||||
- `tests/system/postphase20-installed-node-operating-system.scm.in`
|
||||
- `tests/system/run-postphase20-installed-node-build-reconfigure-xcpng.sh`
|
||||
|
||||
This harness validates the new installed-node workflow on the approved real XCP-ng path.
|
||||
|
||||
## Validation performed
|
||||
|
||||
Approved real XCP-ng path:
|
||||
|
||||
- VM `90490f2e-e8fc-4b7a-388e-5c26f0157289`
|
||||
- VDI `0f1f90d3-48ca-4fa2-91d8-fc6339b95743`
|
||||
|
||||
Promoted native-base result consumed by the installed node declaration:
|
||||
|
||||
- `/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest`
|
||||
|
||||
Validated flow:
|
||||
|
||||
1. boot a Fruix-installed node built from the promoted native-base result
|
||||
2. confirm the installed node exposes:
|
||||
- embedded declaration metadata
|
||||
- bundled node CLI sources
|
||||
3. run in-guest:
|
||||
- `fruix system build`
|
||||
using the node's own embedded declaration inputs
|
||||
4. copy a candidate declaration to the guest
|
||||
5. run in-guest:
|
||||
- `fruix system build /root/candidate.scm --system postphase20-installed-node-operating-system`
|
||||
6. run in-guest:
|
||||
- `fruix system reconfigure /root/candidate.scm --system postphase20-installed-node-operating-system`
|
||||
7. reboot and verify the candidate generation boots
|
||||
8. run in-guest:
|
||||
- `fruix system rollback`
|
||||
9. reboot and verify the original generation boots again
|
||||
|
||||
Passing run:
|
||||
|
||||
- `PASS postphase20-installed-node-build-reconfigure-xcpng`
|
||||
|
||||
Representative metadata:
|
||||
|
||||
```text
|
||||
closure_path=/frx/store/cd4e52d8bff348953939401c8623d4189d7c9432-fruix-system-fruix-node-current
|
||||
current_built_closure=/frx/store/18ee10925a15b48c676463a3359c45ff766e16a0-fruix-system-fruix-node-current
|
||||
candidate_closure=/frx/store/46fc9631faf556c30a1a5f39f718d5d38a3f6ba8-fruix-system-fruix-node-canary
|
||||
reconfigure_closure=/frx/store/46fc9631faf556c30a1a5f39f718d5d38a3f6ba8-fruix-system-fruix-node-canary
|
||||
reconfigure_current_generation=2
|
||||
reconfigure_current_closure=/frx/store/46fc9631faf556c30a1a5f39f718d5d38a3f6ba8-fruix-system-fruix-node-canary
|
||||
reconfigure_rollback_generation=1
|
||||
reconfigure_rollback_closure=/frx/store/cd4e52d8bff348953939401c8623d4189d7c9432-fruix-system-fruix-node-current
|
||||
candidate_hostname=fruix-node-canary
|
||||
rollback_current_generation=1
|
||||
rollback_current_closure=/frx/store/cd4e52d8bff348953939401c8623d4189d7c9432-fruix-system-fruix-node-current
|
||||
rollback_rollback_generation=2
|
||||
rollback_rollback_closure=/frx/store/46fc9631faf556c30a1a5f39f718d5d38a3f6ba8-fruix-system-fruix-node-canary
|
||||
rollback_hostname=fruix-node-current
|
||||
installed_node_build_reconfigure=ok
|
||||
```
|
||||
|
||||
## Important observation
|
||||
|
||||
The no-argument in-node build of the current declaration did not necessarily reproduce the exact original current closure path.
|
||||
|
||||
That is expected with the current model because closure metadata still records builder-local provenance such as the current build host context.
|
||||
|
||||
So the significant validated fact is not strict bit-for-bit closure reuse.
|
||||
|
||||
It is that the installed node can now:
|
||||
|
||||
- read its own declaration inputs locally
|
||||
- build a valid local candidate closure from them
|
||||
- build a different candidate declaration locally
|
||||
- reconfigure itself into that candidate generation
|
||||
- boot the candidate generation
|
||||
- roll back and boot the prior generation again
|
||||
|
||||
## Result
|
||||
|
||||
Fruix-installed machines are now meaningfully closer to real Fruix nodes.
|
||||
|
||||
They no longer only support:
|
||||
|
||||
- `status`
|
||||
- `switch`
|
||||
- `rollback`
|
||||
|
||||
They now also support a validated local node workflow for:
|
||||
|
||||
- reading embedded declaration inputs
|
||||
- building a local candidate closure
|
||||
- reconfiguring into that locally built candidate
|
||||
- rolling back through the same installed generation model
|
||||
|
||||
This is the first concrete step toward a fuller operator-facing Fruix node command surface.
|
||||
@@ -0,0 +1,165 @@
|
||||
# Post-Phase 20: promoted native base result sets as declaration inputs
|
||||
|
||||
Date: 2026-04-06
|
||||
|
||||
## Goal
|
||||
|
||||
Move Fruix from:
|
||||
|
||||
- “the guest built a kernel”
|
||||
|
||||
to:
|
||||
|
||||
- “Fruix materialized a native-base result set with identity X”
|
||||
|
||||
and then prove that a normal Fruix system declaration can consume that promoted result set directly.
|
||||
|
||||
Concretely, the desired product behavior was:
|
||||
|
||||
1. build runs somewhere
|
||||
2. result is recorded in a staging/result root
|
||||
3. Fruix validates the result shape and metadata
|
||||
4. Fruix promotes it into store objects
|
||||
5. system declarations can refer to those promoted artifacts
|
||||
|
||||
Before this step, Fruix already had validated steps 1 through 4.
|
||||
|
||||
This step implemented and validated step 5.
|
||||
|
||||
## What changed
|
||||
|
||||
### First-class promoted result reference in system declarations
|
||||
|
||||
Fruix now has a first-class promoted native-build result reference object.
|
||||
|
||||
Current declaration-level entry points are:
|
||||
|
||||
- `promoted-native-build-result`
|
||||
- `operating-system-from-promoted-native-build-result`
|
||||
|
||||
A declaration can now point at a promoted native-build result bundle in `/frx/store`, for example:
|
||||
|
||||
```scheme
|
||||
(define promoted
|
||||
(promoted-native-build-result
|
||||
#:store-path "/frx/store/...-fruix-native-build-result-..."))
|
||||
|
||||
(define os
|
||||
(operating-system-from-promoted-native-build-result
|
||||
promoted
|
||||
...))
|
||||
```
|
||||
|
||||
### Promoted result bundles now drive system composition
|
||||
|
||||
From a promoted result bundle, Fruix now derives:
|
||||
|
||||
- the effective FreeBSD base metadata used by the system declaration
|
||||
- kernel package identity from the promoted kernel artifact store
|
||||
- bootloader package identity from the promoted bootloader artifact store
|
||||
- base-package identity from the promoted world artifact store
|
||||
- optional development-package identity from the promoted headers artifact store
|
||||
|
||||
This means a system declaration can now be based on a promoted native-build result set rather than only on source-driven base-package reconstruction.
|
||||
|
||||
### Closure metadata now records promoted-result provenance explicitly
|
||||
|
||||
When a system declaration uses a promoted native-build result set, Fruix now records that explicitly in the resulting closure metadata.
|
||||
|
||||
New closure metadata includes:
|
||||
|
||||
- `metadata/promoted-native-build-result.scm`
|
||||
- `metadata/store-layout.scm` entries for:
|
||||
- promoted result summary
|
||||
- promoted artifact stores
|
||||
|
||||
The system closure also retains the promoted result bundle itself as an explicit reference in:
|
||||
|
||||
- `/frx/store/...-fruix-system-.../.references`
|
||||
|
||||
So the resulting deployed closure does not merely happen to contain files copied from a promoted artifact; it explicitly records which promoted result set it came from.
|
||||
|
||||
## Implementation notes
|
||||
|
||||
The key plumbing additions were:
|
||||
|
||||
- a promoted native-build result record in:
|
||||
- `modules/fruix/system/freebsd/model.scm`
|
||||
- promoted-result readers/helpers in:
|
||||
- `modules/fruix/system/freebsd/build.scm`
|
||||
- direct system-construction helper:
|
||||
- `operating-system-from-promoted-native-build-result`
|
||||
- support for consuming promoted artifact stores directly when materializing packages
|
||||
- closure/store-layout metadata wiring in:
|
||||
- `modules/fruix/system/freebsd/media.scm`
|
||||
|
||||
The important product-level effect is that promoted native-build results are no longer only post-build artifacts. They are now declaration inputs.
|
||||
|
||||
## Validation harness
|
||||
|
||||
Added:
|
||||
|
||||
- `tests/system/phase20-promoted-native-base-operating-system.scm.in`
|
||||
- `tests/system/run-phase20-promoted-native-base-declaration-xcpng.sh`
|
||||
|
||||
The harness supports two modes:
|
||||
|
||||
- use an explicit `RESULT_STORE=/frx/store/...-fruix-native-build-result-...`
|
||||
- or, if no result store is supplied, first run the validated host-initiated promotion path and consume that result
|
||||
|
||||
## Validation performed
|
||||
|
||||
Validated on the approved real XCP-ng path using the promoted `ssh-guest` result bundle:
|
||||
|
||||
- result bundle:
|
||||
- `/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest`
|
||||
- VM:
|
||||
- `90490f2e-e8fc-4b7a-388e-5c26f0157289`
|
||||
- VDI:
|
||||
- `0f1f90d3-48ca-4fa2-91d8-fc6339b95743`
|
||||
|
||||
Passing run:
|
||||
|
||||
- `PASS phase20-promoted-native-base-declaration-xcpng`
|
||||
|
||||
Representative metadata:
|
||||
|
||||
```text
|
||||
closure_path=/frx/store/ac1e6dcfe67d3cde49d4fd5da97740f6244276b4-fruix-system-fruix-freebsd
|
||||
result_store=/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest
|
||||
executor_kind=ssh-guest
|
||||
executor_name=ssh-guest
|
||||
executor_version=1
|
||||
world_store=/frx/store/89c7a71c3df148a1f99b13d57fd6be88243eb2cb-fruix-native-world-15.0-STABLE-ssh-guest
|
||||
kernel_store=/frx/store/93bac81122022b40438d356146a6854b4ee48513-fruix-native-kernel-15.0-STABLE-ssh-guest
|
||||
headers_store=/frx/store/dd7f39f526bca4849caf1eaf96ae25d29b43493c-fruix-native-headers-15.0-STABLE-ssh-guest
|
||||
bootloader_store=/frx/store/78b1c6b0b5c0c2c1549f5f42f3d64b6d9293669b-fruix-native-bootloader-15.0-STABLE-ssh-guest
|
||||
kernel_link=/frx/store/93bac81122022b40438d356146a6854b4ee48513-fruix-native-kernel-15.0-STABLE-ssh-guest/boot/kernel/kernel
|
||||
bootloader_link=/frx/store/78b1c6b0b5c0c2c1549f5f42f3d64b6d9293669b-fruix-native-bootloader-15.0-STABLE-ssh-guest/boot/loader.efi
|
||||
guest_kernel_link=/frx/store/93bac81122022b40438d356146a6854b4ee48513-fruix-native-kernel-15.0-STABLE-ssh-guest/boot/kernel/kernel
|
||||
guest_bootloader_link=/frx/store/78b1c6b0b5c0c2c1549f5f42f3d64b6d9293669b-fruix-native-bootloader-15.0-STABLE-ssh-guest/boot/loader.efi
|
||||
guest_uname=FreeBSD 15.0-STABLE
|
||||
promoted_native_base_declaration=ok
|
||||
```
|
||||
|
||||
## Validated facts
|
||||
|
||||
The real-VM validation proved that Fruix can now:
|
||||
|
||||
- consume a promoted native-build result bundle directly from a declaration
|
||||
- materialize a normal system closure from that promoted identity
|
||||
- retain explicit promoted-result provenance in closure metadata
|
||||
- boot the resulting system successfully on the approved XCP-ng path
|
||||
- keep the closure's kernel and bootloader linked directly to the promoted artifact stores
|
||||
- preserve the promoted result-bundle store itself as an explicit closure reference
|
||||
|
||||
So the operator-facing story is now materially better:
|
||||
|
||||
- not only “a build happened somewhere”
|
||||
- but “this system declaration is based on promoted native-base result X”
|
||||
|
||||
## Result
|
||||
|
||||
Promoted native-build result sets are now first-class Fruix declaration inputs.
|
||||
|
||||
That is the point where the native FreeBSD base path stops being only a build/promotion harness and starts acting more like real product behavior.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Fruix system deployment workflow
|
||||
|
||||
Date: 2026-04-05
|
||||
Date: 2026-04-06
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -178,12 +178,32 @@ Installed Fruix systems now also ship a small in-guest deployment helper at:
|
||||
Current validated in-guest commands are:
|
||||
|
||||
```sh
|
||||
fruix system build
|
||||
fruix system reconfigure
|
||||
fruix system status
|
||||
fruix system switch /frx/store/...-fruix-system-...
|
||||
fruix system rollback
|
||||
```
|
||||
|
||||
Current intended usage:
|
||||
Installed systems now carry canonical declaration state in:
|
||||
|
||||
- `/run/current-system/metadata/system-declaration.scm`
|
||||
- `/run/current-system/metadata/system-declaration-info.scm`
|
||||
- `/run/current-system/metadata/system-declaration-system`
|
||||
|
||||
So the in-guest helper can now build from the node's own embedded declaration inputs.
|
||||
|
||||
Current validated build/reconfigure behavior is:
|
||||
|
||||
- `fruix system build`
|
||||
- with no extra arguments, builds from the embedded current declaration
|
||||
- `fruix system reconfigure`
|
||||
- with no extra arguments, builds from the embedded current declaration and stages a switch to the resulting closure
|
||||
- both commands can also take an explicit declaration file plus `--system NAME`
|
||||
|
||||
Current intended usage now has two validated patterns.
|
||||
|
||||
### Pattern A: build elsewhere, then switch/rollback locally
|
||||
|
||||
1. build a candidate closure on the operator side with `./bin/fruix system build`
|
||||
2. ensure that candidate closure is present on the installed target's `/frx/store`
|
||||
@@ -192,21 +212,56 @@ Current intended usage:
|
||||
5. if needed, run `fruix system rollback`
|
||||
6. reboot back into the recorded rollback generation
|
||||
|
||||
Important current limitation:
|
||||
Important current limitation of this lower-level pattern:
|
||||
|
||||
- `fruix system switch` does **not** yet fetch or copy the candidate closure onto the target for you
|
||||
- it assumes the selected closure is already present in the installed system's `/frx/store`
|
||||
|
||||
### In-guest development environment
|
||||
### Pattern B: build and reconfigure from the node itself
|
||||
|
||||
Opt-in systems can also expose a separate development overlay under:
|
||||
1. inspect or edit the node declaration inputs
|
||||
- embedded current declaration, or
|
||||
- an explicit replacement declaration file
|
||||
2. run:
|
||||
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
```sh
|
||||
fruix system build
|
||||
```
|
||||
|
||||
Those systems now ship a helper at:
|
||||
or:
|
||||
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
```sh
|
||||
fruix system build /path/to/candidate.scm --system my-operating-system
|
||||
```
|
||||
|
||||
3. stage a local generation update with:
|
||||
|
||||
```sh
|
||||
fruix system reconfigure
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```sh
|
||||
fruix system reconfigure /path/to/candidate.scm --system my-operating-system
|
||||
```
|
||||
|
||||
4. reboot into the staged generation
|
||||
5. if needed, run `fruix system rollback`
|
||||
6. reboot back into the recorded prior generation
|
||||
|
||||
### In-guest development and build environments
|
||||
|
||||
Opt-in systems can now expose two separate overlays above the main runtime profile:
|
||||
|
||||
- development:
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- build:
|
||||
- `/run/current-system/build-profile`
|
||||
- `/run/current-build`
|
||||
- `/usr/local/bin/fruix-build-environment`
|
||||
|
||||
Intended use:
|
||||
|
||||
@@ -214,19 +269,53 @@ Intended use:
|
||||
eval "$(/usr/local/bin/fruix-development-environment)"
|
||||
```
|
||||
|
||||
That helper exports a development-oriented environment while keeping the main runtime profile separate. The validated Phase 20 path currently uses this to expose at least:
|
||||
for interactive development work, and:
|
||||
|
||||
```sh
|
||||
eval "$(/usr/local/bin/fruix-build-environment)"
|
||||
```
|
||||
|
||||
for a narrower native base-build contract.
|
||||
|
||||
The current split is:
|
||||
|
||||
- runtime profile
|
||||
- development profile
|
||||
- build profile
|
||||
|
||||
The development helper remains intentionally interactive and currently exposes at least:
|
||||
|
||||
- native headers under `usr/include`
|
||||
- FreeBSD `share/mk` files for `bsd.*.mk`
|
||||
- Clang toolchain commands such as `cc`, `c++`, `ar`, `ranlib`, and `nm`
|
||||
- `MAKEFLAGS` pointing at the development profile's `usr/share/mk`
|
||||
|
||||
For native base-build compatibility, development-enabled systems also now expose canonical links at:
|
||||
The build helper is intentionally more sanitized and less interactive. It clears development-shell variables such as:
|
||||
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
- `MAKEFLAGS`
|
||||
- `CPPFLAGS`
|
||||
- `CFLAGS`
|
||||
- `CXXFLAGS`
|
||||
- `LDFLAGS`
|
||||
|
||||
This is the current Fruix-native way to make a running system suitable for controlled native base-development work without merging development content back into the main runtime profile.
|
||||
and then exposes build-oriented paths such as:
|
||||
|
||||
- `FRUIX_BUILD_PROFILE`
|
||||
- `FRUIX_BUILD_INCLUDE`
|
||||
- `FRUIX_BUILD_SHARE_MK`
|
||||
- `FRUIX_BUILD_CC`
|
||||
- `FRUIX_BUILD_CXX`
|
||||
- `FRUIX_BUILD_AR`
|
||||
- `FRUIX_BUILD_RANLIB`
|
||||
- `FRUIX_BUILD_NM`
|
||||
- `FRUIX_BMAKE`
|
||||
|
||||
For native base-build compatibility, build-enabled systems now expose canonical links at:
|
||||
|
||||
- `/usr/include -> /run/current-system/build-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/build-profile/usr/share/mk`
|
||||
|
||||
So Fruix now separates interactive development support from the stricter environment used for `buildworld` / `buildkernel` style work, instead of treating them as one overlay.
|
||||
|
||||
### Host-initiated native base builds inside a Fruix-managed guest
|
||||
|
||||
@@ -274,7 +363,7 @@ FRUIX_SELF_HOSTED_NATIVE_BUILD_JOBS=8 \
|
||||
|
||||
That helper:
|
||||
|
||||
1. verifies the development overlay and canonical compatibility links
|
||||
1. evaluates the build helper and verifies the build overlay plus canonical compatibility links
|
||||
2. recovers the materialized FreeBSD source store from:
|
||||
- `/run/current-system/metadata/store-layout.scm`
|
||||
3. runs the native FreeBSD build/install phases inside the guest
|
||||
@@ -291,8 +380,9 @@ That helper:
|
||||
|
||||
Important current detail:
|
||||
|
||||
- the self-hosted helper intentionally **sanitizes** development-shell exports such as `MAKEFLAGS`, `CPPFLAGS`, `CFLAGS`, `CXXFLAGS`, and `LDFLAGS` before `buildworld`
|
||||
- directly reusing the full development-shell environment polluted FreeBSD's bootstrap path and was not reliable enough for real world/kernel builds
|
||||
- the self-hosted helper now uses the separate `fruix-build-environment` contract instead of reusing the interactive development helper wholesale
|
||||
- that build helper intentionally clears development-shell exports such as `MAKEFLAGS`, `CPPFLAGS`, `CFLAGS`, `CXXFLAGS`, and `LDFLAGS` before `buildworld`
|
||||
- this keeps the base-build path closer to the exact contract needed for real world/kernel bootstrap work
|
||||
|
||||
So the validated Phase 20.3 answer is:
|
||||
|
||||
@@ -337,7 +427,7 @@ Current metadata split:
|
||||
|
||||
The promoted store objects record explicit Fruix-native metadata including at least:
|
||||
|
||||
- executor / executor-version
|
||||
- executor kind / name / version
|
||||
- run-id / guest-host-name
|
||||
- closure path
|
||||
- source store provenance
|
||||
@@ -353,6 +443,87 @@ This is the current Fruix-native answer to the question:
|
||||
- where should immutable native-build identity live?
|
||||
- `/frx/store/...`
|
||||
|
||||
### Using promoted native-build results in system declarations
|
||||
|
||||
Fruix system declarations can now refer directly to a promoted native-build result bundle.
|
||||
|
||||
Current declaration-level helpers are:
|
||||
|
||||
- `promoted-native-build-result`
|
||||
- `operating-system-from-promoted-native-build-result`
|
||||
|
||||
Representative pattern:
|
||||
|
||||
```scheme
|
||||
(define promoted
|
||||
(promoted-native-build-result
|
||||
#:store-path "/frx/store/...-fruix-native-build-result-..."))
|
||||
|
||||
(define os
|
||||
(operating-system-from-promoted-native-build-result
|
||||
promoted
|
||||
#:host-name "fruix-freebsd"
|
||||
...))
|
||||
```
|
||||
|
||||
That now gives Fruix a more product-like story:
|
||||
|
||||
1. a build runs under some executor policy
|
||||
2. Fruix records the staged mutable result
|
||||
3. Fruix promotes it into immutable store identities
|
||||
4. a later system declaration can point at that promoted result identity
|
||||
5. Fruix materializes and boots a normal system from that promoted identity
|
||||
|
||||
The resulting closure now records that provenance explicitly through:
|
||||
|
||||
- `metadata/promoted-native-build-result.scm`
|
||||
- `metadata/store-layout.scm`
|
||||
- closure references that retain the selected result-bundle store path
|
||||
|
||||
So the operator-facing statement is now:
|
||||
|
||||
- “this Fruix system is based on promoted native-base result X”
|
||||
|
||||
not only:
|
||||
|
||||
- “some earlier build happened and its files were copied somewhere.”
|
||||
|
||||
### Native-build executor model
|
||||
|
||||
Fruix now has an explicit executor model for native base builds.
|
||||
|
||||
Current executor kinds are:
|
||||
|
||||
- `host`
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
|
||||
and the intended future extension points are:
|
||||
|
||||
- `jail`
|
||||
- `remote-builder`
|
||||
|
||||
The important change is architectural:
|
||||
|
||||
- declared source identity stays the same
|
||||
- expected artifact kinds stay the same
|
||||
- result/promotion metadata shape stays the same
|
||||
- only the executor policy changes
|
||||
|
||||
So “where the build runs” is now treated as executor policy rather than as a separate native-build architecture each time.
|
||||
|
||||
Current end-to-end validated executors for the staged-result-plus-promotion model are:
|
||||
|
||||
- `ssh-guest`
|
||||
- `self-hosted`
|
||||
|
||||
Both now converge on the same Fruix-native flow:
|
||||
|
||||
1. run the build under a selected executor
|
||||
2. stage a result root under `/var/lib/fruix/native-builds/...`
|
||||
3. emit the same promotion/provenance shape
|
||||
4. promote the result into immutable `/frx/store/...` objects
|
||||
|
||||
## Deployment patterns
|
||||
|
||||
### 1. Build-first workflow
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(define-module (fruix system freebsd)
|
||||
#:use-module (fruix system freebsd model)
|
||||
#:use-module (fruix system freebsd source)
|
||||
#:use-module (fruix system freebsd executor)
|
||||
#:use-module (fruix system freebsd build)
|
||||
#:use-module (fruix system freebsd media)
|
||||
#:re-export (user-group
|
||||
@@ -25,14 +26,21 @@
|
||||
file-system-type
|
||||
file-system-options
|
||||
file-system-needed-for-boot?
|
||||
promoted-native-build-result?
|
||||
promoted-native-build-result-store-path
|
||||
promoted-native-build-result-metadata-file
|
||||
promoted-native-build-result-metadata
|
||||
promoted-native-build-result-spec
|
||||
operating-system
|
||||
operating-system?
|
||||
operating-system-host-name
|
||||
operating-system-freebsd-base
|
||||
operating-system-native-build-result
|
||||
operating-system-kernel
|
||||
operating-system-bootloader
|
||||
operating-system-base-packages
|
||||
operating-system-development-packages
|
||||
operating-system-build-packages
|
||||
operating-system-users
|
||||
operating-system-groups
|
||||
operating-system-file-systems
|
||||
@@ -44,6 +52,25 @@
|
||||
operating-system-root-authorized-keys
|
||||
validate-operating-system
|
||||
materialize-freebsd-source
|
||||
native-build-executor
|
||||
native-build-executor?
|
||||
native-build-executor-ref
|
||||
native-build-executor-kind
|
||||
native-build-executor-name
|
||||
native-build-executor-version
|
||||
native-build-executor-properties
|
||||
normalize-native-build-executor
|
||||
host-native-build-executor
|
||||
ssh-guest-native-build-executor
|
||||
self-hosted-native-build-executor
|
||||
promoted-native-build-result
|
||||
promoted-native-build-result->freebsd-base
|
||||
promoted-native-build-result-artifact-store
|
||||
promoted-native-build-result-kernel-package
|
||||
promoted-native-build-result-bootloader-package
|
||||
promoted-native-build-result-base-packages
|
||||
promoted-native-build-result-development-packages
|
||||
operating-system-from-promoted-native-build-result
|
||||
promote-native-build-result
|
||||
operating-system-closure-spec
|
||||
operating-system-install-spec
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#:use-module (fruix packages freebsd)
|
||||
#:use-module (fruix system freebsd model)
|
||||
#:use-module (fruix system freebsd source)
|
||||
#:use-module (fruix system freebsd executor)
|
||||
#:use-module (fruix system freebsd utils)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module (ice-9 format)
|
||||
@@ -10,6 +11,14 @@
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-13)
|
||||
#:export (host-freebsd-provenance
|
||||
promoted-native-build-result
|
||||
promoted-native-build-result->freebsd-base
|
||||
promoted-native-build-result-artifact-store
|
||||
promoted-native-build-result-kernel-package
|
||||
promoted-native-build-result-bootloader-package
|
||||
promoted-native-build-result-base-packages
|
||||
promoted-native-build-result-development-packages
|
||||
operating-system-from-promoted-native-build-result
|
||||
materialize-freebsd-package
|
||||
promote-native-build-result
|
||||
materialize-prefix))
|
||||
@@ -340,53 +349,55 @@
|
||||
(append overrides plan)))
|
||||
|
||||
(define* (materialize-freebsd-package package store-dir cache #:optional source-cache)
|
||||
(let* ((source-cache (or source-cache (make-hash-table)))
|
||||
(input-paths (map (lambda (input)
|
||||
(materialize-freebsd-package input store-dir cache source-cache))
|
||||
(freebsd-package-inputs package)))
|
||||
(prepared-package
|
||||
(if (freebsd-native-build-package? package)
|
||||
(let* ((source (plan-freebsd-source (freebsd-package-install-plan package)))
|
||||
(source-result (materialize-freebsd-source/cached source store-dir source-cache))
|
||||
(plan (plan-with-materialized-source (freebsd-package-install-plan package)
|
||||
source-result)))
|
||||
(package-with-install-plan package plan))
|
||||
package))
|
||||
(effective-input-paths
|
||||
(if (freebsd-native-build-package? package)
|
||||
(cons (build-plan-ref (freebsd-package-install-plan prepared-package)
|
||||
'materialized-source-store
|
||||
#f)
|
||||
input-paths)
|
||||
input-paths))
|
||||
(effective-input-paths (filter identity effective-input-paths))
|
||||
(manifest (package-manifest-string prepared-package effective-input-paths))
|
||||
(cache-key (sha256-string manifest))
|
||||
(cached (hash-ref cache cache-key #f)))
|
||||
(if cached
|
||||
cached
|
||||
(let* ((display-name (string-append (freebsd-package-name prepared-package)
|
||||
"-"
|
||||
(freebsd-package-version prepared-package)))
|
||||
(output-path (make-store-path store-dir display-name manifest
|
||||
#:kind 'freebsd-package)))
|
||||
(unless (file-exists? output-path)
|
||||
(case (freebsd-package-build-system prepared-package)
|
||||
((copy-build-system)
|
||||
(mkdir-p output-path)
|
||||
(for-each (lambda (entry)
|
||||
(materialize-plan-entry output-path entry))
|
||||
(freebsd-package-install-plan prepared-package))
|
||||
(write-file (string-append output-path "/.references")
|
||||
(string-join effective-input-paths "\n"))
|
||||
(write-file (string-append output-path "/.fruix-package") manifest))
|
||||
((freebsd-world-build-system freebsd-kernel-build-system)
|
||||
(materialize-native-freebsd-package prepared-package effective-input-paths manifest output-path))
|
||||
(else
|
||||
(error (format #f "unsupported package build system: ~a"
|
||||
(freebsd-package-build-system prepared-package))))))
|
||||
(hash-set! cache cache-key output-path)
|
||||
output-path))))
|
||||
(if (existing-store-package? package)
|
||||
(validate-existing-store-package package)
|
||||
(let* ((source-cache (or source-cache (make-hash-table)))
|
||||
(input-paths (map (lambda (input)
|
||||
(materialize-freebsd-package input store-dir cache source-cache))
|
||||
(freebsd-package-inputs package)))
|
||||
(prepared-package
|
||||
(if (freebsd-native-build-package? package)
|
||||
(let* ((source (plan-freebsd-source (freebsd-package-install-plan package)))
|
||||
(source-result (materialize-freebsd-source/cached source store-dir source-cache))
|
||||
(plan (plan-with-materialized-source (freebsd-package-install-plan package)
|
||||
source-result)))
|
||||
(package-with-install-plan package plan))
|
||||
package))
|
||||
(effective-input-paths
|
||||
(if (freebsd-native-build-package? package)
|
||||
(cons (build-plan-ref (freebsd-package-install-plan prepared-package)
|
||||
'materialized-source-store
|
||||
#f)
|
||||
input-paths)
|
||||
input-paths))
|
||||
(effective-input-paths (filter identity effective-input-paths))
|
||||
(manifest (package-manifest-string prepared-package effective-input-paths))
|
||||
(cache-key (sha256-string manifest))
|
||||
(cached (hash-ref cache cache-key #f)))
|
||||
(if cached
|
||||
cached
|
||||
(let* ((display-name (string-append (freebsd-package-name prepared-package)
|
||||
"-"
|
||||
(freebsd-package-version prepared-package)))
|
||||
(output-path (make-store-path store-dir display-name manifest
|
||||
#:kind 'freebsd-package)))
|
||||
(unless (file-exists? output-path)
|
||||
(case (freebsd-package-build-system prepared-package)
|
||||
((copy-build-system)
|
||||
(mkdir-p output-path)
|
||||
(for-each (lambda (entry)
|
||||
(materialize-plan-entry output-path entry))
|
||||
(freebsd-package-install-plan prepared-package))
|
||||
(write-file (string-append output-path "/.references")
|
||||
(string-join effective-input-paths "\n"))
|
||||
(write-file (string-append output-path "/.fruix-package") manifest))
|
||||
((freebsd-world-build-system freebsd-kernel-build-system)
|
||||
(materialize-native-freebsd-package prepared-package effective-input-paths manifest output-path))
|
||||
(else
|
||||
(error (format #f "unsupported package build system: ~a"
|
||||
(freebsd-package-build-system prepared-package))))))
|
||||
(hash-set! cache cache-key output-path)
|
||||
output-path)))))
|
||||
|
||||
|
||||
(define native-build-result-promotion-version "1")
|
||||
@@ -396,6 +407,32 @@
|
||||
((_ . value) value)
|
||||
(#f default)))
|
||||
|
||||
(define (native-build-result-executor result)
|
||||
(let* ((executor (native-build-result-ref result 'executor #f))
|
||||
(legacy-version (native-build-result-ref result 'executor-version "legacy")))
|
||||
(cond
|
||||
((native-build-executor? executor)
|
||||
executor)
|
||||
((string? executor)
|
||||
(let ((normalized (normalize-native-build-executor executor)))
|
||||
`((kind . ,(native-build-executor-kind normalized))
|
||||
(name . ,(native-build-executor-name normalized))
|
||||
(version . ,legacy-version)
|
||||
(properties . ,(native-build-executor-properties normalized)))))
|
||||
(else
|
||||
(native-build-executor #:kind 'unknown
|
||||
#:name "unknown"
|
||||
#:version legacy-version)))))
|
||||
|
||||
(define (native-build-result-executor-kind result)
|
||||
(native-build-executor-kind (native-build-result-executor result)))
|
||||
|
||||
(define (native-build-result-executor-name result)
|
||||
(native-build-executor-name (native-build-result-executor result)))
|
||||
|
||||
(define (native-build-result-executor-version result)
|
||||
(native-build-executor-version (native-build-result-executor result)))
|
||||
|
||||
(define (read-native-build-result result-root)
|
||||
(let ((promotion-file (string-append result-root "/promotion.scm")))
|
||||
(unless (file-exists? promotion-file)
|
||||
@@ -406,6 +443,237 @@
|
||||
(error "unsupported native build result promotion version" promotion-file))
|
||||
result)))
|
||||
|
||||
(define existing-store-package-build-system 'existing-store-item-build-system)
|
||||
|
||||
(define (existing-store-package? package)
|
||||
(eq? (freebsd-package-build-system package)
|
||||
existing-store-package-build-system))
|
||||
|
||||
(define (existing-store-package-ref package key default)
|
||||
(build-plan-ref (freebsd-package-install-plan package) key default))
|
||||
|
||||
(define (validate-existing-store-package package)
|
||||
(let* ((store-path (existing-store-package-ref package 'store-path #f))
|
||||
(required-file (existing-store-package-ref package 'required-file #f))
|
||||
(metadata-file (existing-store-package-ref package 'metadata-file #f)))
|
||||
(unless (and (string? store-path) (file-exists? store-path))
|
||||
(error "existing-store package is missing a valid store path" package store-path))
|
||||
(when metadata-file
|
||||
(unless (file-exists? metadata-file)
|
||||
(error "existing-store package metadata file is missing" package metadata-file)))
|
||||
(when required-file
|
||||
(unless (file-exists? (string-append store-path "/" required-file))
|
||||
(error "existing-store package is missing required file"
|
||||
package
|
||||
(string-append store-path "/" required-file))))
|
||||
store-path))
|
||||
|
||||
(define (normalize-promoted-native-build-result value)
|
||||
(cond
|
||||
((promoted-native-build-result? value)
|
||||
value)
|
||||
((string? value)
|
||||
(promoted-native-build-result #:store-path value))
|
||||
(else
|
||||
(error "expected a promoted native build result or store path" value))))
|
||||
|
||||
(define (read-promoted-native-build-artifact-metadata metadata-file)
|
||||
(unless (file-exists? metadata-file)
|
||||
(error "promoted native build artifact metadata file is missing" metadata-file))
|
||||
(let ((metadata (call-with-input-file metadata-file read)))
|
||||
(unless (equal? (native-build-result-ref metadata 'native-build-object-version #f)
|
||||
native-build-result-promotion-version)
|
||||
(error "unsupported promoted native build object version" metadata-file))
|
||||
(unless (eq? (native-build-result-ref metadata 'object-kind #f) 'artifact)
|
||||
(error "promoted native build object is not an artifact" metadata-file))
|
||||
metadata))
|
||||
|
||||
(define (promoted-native-build-result-artifact-entry result artifact-kind)
|
||||
(let* ((metadata (promoted-native-build-result-metadata result))
|
||||
(artifacts (native-build-result-ref metadata 'artifacts '()))
|
||||
(entry (find (lambda (item)
|
||||
(eq? (native-build-result-ref item 'artifact-kind #f)
|
||||
artifact-kind))
|
||||
artifacts)))
|
||||
(unless entry
|
||||
(error "promoted native build result is missing artifact entry" artifact-kind))
|
||||
entry))
|
||||
|
||||
(define (promoted-native-build-result-artifact-store result artifact-kind)
|
||||
(let* ((result (normalize-promoted-native-build-result result))
|
||||
(entry (promoted-native-build-result-artifact-entry result artifact-kind))
|
||||
(store-path (native-build-result-ref entry 'store-path #f))
|
||||
(metadata-file (native-build-result-ref entry 'metadata-file #f))
|
||||
(artifact-metadata (and metadata-file
|
||||
(read-promoted-native-build-artifact-metadata metadata-file)))
|
||||
(required-file (and artifact-metadata
|
||||
(native-build-result-ref artifact-metadata 'required-file #f))))
|
||||
(unless (and (string? store-path) (file-exists? store-path))
|
||||
(error "promoted native build result is missing artifact store" artifact-kind store-path))
|
||||
(when artifact-metadata
|
||||
(unless (eq? (native-build-result-ref artifact-metadata 'artifact-kind #f)
|
||||
artifact-kind)
|
||||
(error "promoted native build artifact metadata kind mismatch"
|
||||
artifact-kind
|
||||
metadata-file)))
|
||||
(when required-file
|
||||
(unless (file-exists? (string-append store-path "/" required-file))
|
||||
(error "promoted native build artifact store is missing required file"
|
||||
artifact-kind
|
||||
(string-append store-path "/" required-file))))
|
||||
store-path))
|
||||
|
||||
(define* (promoted-native-build-result #:key store-path)
|
||||
(unless (and (string? store-path) (file-exists? store-path))
|
||||
(error "promoted native build result store path does not exist" store-path))
|
||||
(let* ((metadata-file (string-append store-path "/.fruix-native-build-result.scm")))
|
||||
(unless (file-exists? metadata-file)
|
||||
(error "promoted native build result store is missing metadata" metadata-file))
|
||||
(let* ((metadata (call-with-input-file metadata-file read))
|
||||
(result (make-promoted-native-build-result store-path metadata-file metadata)))
|
||||
(unless (equal? (native-build-result-ref metadata 'native-build-result-version #f)
|
||||
native-build-result-promotion-version)
|
||||
(error "unsupported promoted native build result version" metadata-file))
|
||||
(unless (eq? (native-build-result-ref metadata 'object-kind #f) 'result-bundle)
|
||||
(error "promoted native build result store does not contain a result bundle" metadata-file))
|
||||
(for-each (lambda (artifact-kind)
|
||||
(promoted-native-build-result-artifact-store result artifact-kind))
|
||||
'(world kernel headers bootloader))
|
||||
result)))
|
||||
|
||||
(define (promoted-native-build-result->freebsd-base result)
|
||||
(let* ((result (normalize-promoted-native-build-result result))
|
||||
(metadata (promoted-native-build-result-metadata result))
|
||||
(base (native-build-result-ref metadata 'freebsd-base '()))
|
||||
(source (native-build-result-ref metadata 'source '()))
|
||||
(source-root (or (native-build-result-ref source 'source-root #f)
|
||||
(native-build-result-ref base 'source-root #f)
|
||||
"/usr/src"))
|
||||
(source-name (string-append "promoted-native-build-result-source-"
|
||||
(path-basename
|
||||
(promoted-native-build-result-store-path result))))
|
||||
(synthetic-source (freebsd-source #:name source-name
|
||||
#:kind 'local-tree
|
||||
#:path source-root)))
|
||||
(freebsd-base #:name (native-build-result-ref base 'name "promoted-native-build-result")
|
||||
#:version-label (native-build-result-ref base 'version-label "unknown")
|
||||
#:release (native-build-result-ref base 'release "unknown")
|
||||
#:branch (native-build-result-ref base 'branch "unknown")
|
||||
#:source synthetic-source
|
||||
#:source-root (native-build-result-ref base 'source-root source-root)
|
||||
#:target (native-build-result-ref base 'target "amd64")
|
||||
#:target-arch (native-build-result-ref base 'target-arch "amd64")
|
||||
#:kernconf (native-build-result-ref base 'kernconf "GENERIC"))))
|
||||
|
||||
(define (promoted-native-build-result-artifact-package result artifact-kind
|
||||
package-name synopsis description)
|
||||
(let* ((result (normalize-promoted-native-build-result result))
|
||||
(metadata (promoted-native-build-result-metadata result))
|
||||
(base (native-build-result-ref metadata 'freebsd-base '()))
|
||||
(entry (promoted-native-build-result-artifact-entry result artifact-kind))
|
||||
(store-path (promoted-native-build-result-artifact-store result artifact-kind))
|
||||
(metadata-file (native-build-result-ref entry 'metadata-file #f))
|
||||
(artifact-metadata (and metadata-file
|
||||
(read-promoted-native-build-artifact-metadata metadata-file)))
|
||||
(required-file (and artifact-metadata
|
||||
(native-build-result-ref artifact-metadata 'required-file #f))))
|
||||
(freebsd-package
|
||||
#:name package-name
|
||||
#:version (native-build-result-ref base 'version-label "unknown")
|
||||
#:build-system existing-store-package-build-system
|
||||
#:home-page "https://www.freebsd.org/"
|
||||
#:synopsis synopsis
|
||||
#:description description
|
||||
#:license 'bsd-2
|
||||
#:install-plan `((store-path . ,store-path)
|
||||
(metadata-file . ,metadata-file)
|
||||
(required-file . ,required-file)
|
||||
(artifact-kind . ,artifact-kind)
|
||||
(result-store . ,(promoted-native-build-result-store-path result))))))
|
||||
|
||||
(define (promoted-native-build-result-world-package result)
|
||||
(promoted-native-build-result-artifact-package
|
||||
result
|
||||
'world
|
||||
"freebsd-promoted-world"
|
||||
"Promoted Fruix-native FreeBSD world artifact"
|
||||
"FreeBSD world artifact imported from a promoted Fruix native-build result bundle."))
|
||||
|
||||
(define (promoted-native-build-result-kernel-package result)
|
||||
(promoted-native-build-result-artifact-package
|
||||
result
|
||||
'kernel
|
||||
"freebsd-promoted-kernel"
|
||||
"Promoted Fruix-native FreeBSD kernel artifact"
|
||||
"FreeBSD kernel artifact imported from a promoted Fruix native-build result bundle."))
|
||||
|
||||
(define (promoted-native-build-result-bootloader-package result)
|
||||
(promoted-native-build-result-artifact-package
|
||||
result
|
||||
'bootloader
|
||||
"freebsd-promoted-bootloader"
|
||||
"Promoted Fruix-native FreeBSD bootloader artifact"
|
||||
"FreeBSD bootloader artifact imported from a promoted Fruix native-build result bundle."))
|
||||
|
||||
(define (promoted-native-build-result-headers-package result)
|
||||
(promoted-native-build-result-artifact-package
|
||||
result
|
||||
'headers
|
||||
"freebsd-promoted-headers"
|
||||
"Promoted Fruix-native FreeBSD headers artifact"
|
||||
"FreeBSD headers artifact imported from a promoted Fruix native-build result bundle."))
|
||||
|
||||
(define (promoted-native-build-result-base-packages result)
|
||||
(list (promoted-native-build-result-world-package result)))
|
||||
|
||||
(define (promoted-native-build-result-development-packages result)
|
||||
(list (promoted-native-build-result-headers-package result)))
|
||||
|
||||
(define* (operating-system-from-promoted-native-build-result result
|
||||
#:key
|
||||
(host-name #f)
|
||||
(freebsd-base #f)
|
||||
(kernel #f)
|
||||
(bootloader #f)
|
||||
(base-packages #f)
|
||||
(development-packages #f)
|
||||
(users #f)
|
||||
(groups #f)
|
||||
(file-systems #f)
|
||||
(services #f)
|
||||
(loader-entries #f)
|
||||
(rc-conf-entries #f)
|
||||
(init-mode #f)
|
||||
(ready-marker #f)
|
||||
(root-authorized-keys #f))
|
||||
(let* ((result (normalize-promoted-native-build-result result))
|
||||
(defaults default-minimal-operating-system)
|
||||
(fallback (lambda (value thunk)
|
||||
(if (eq? value #f) (thunk) value))))
|
||||
(operating-system
|
||||
#:host-name (fallback host-name (lambda () (operating-system-host-name defaults)))
|
||||
#:freebsd-base (fallback freebsd-base (lambda ()
|
||||
(promoted-native-build-result->freebsd-base result)))
|
||||
#:native-build-result result
|
||||
#:kernel (fallback kernel (lambda ()
|
||||
(promoted-native-build-result-kernel-package result)))
|
||||
#:bootloader (fallback bootloader (lambda ()
|
||||
(promoted-native-build-result-bootloader-package result)))
|
||||
#:base-packages (fallback base-packages (lambda ()
|
||||
(promoted-native-build-result-base-packages result)))
|
||||
#:development-packages (fallback development-packages (lambda ()
|
||||
(operating-system-development-packages defaults)))
|
||||
#:users (fallback users (lambda () (operating-system-users defaults)))
|
||||
#:groups (fallback groups (lambda () (operating-system-groups defaults)))
|
||||
#:file-systems (fallback file-systems (lambda () (operating-system-file-systems defaults)))
|
||||
#:services (fallback services (lambda () (operating-system-services defaults)))
|
||||
#:loader-entries (fallback loader-entries (lambda () (operating-system-loader-entries defaults)))
|
||||
#:rc-conf-entries (fallback rc-conf-entries (lambda () (operating-system-rc-conf-entries defaults)))
|
||||
#:init-mode (fallback init-mode (lambda () (operating-system-init-mode defaults)))
|
||||
#:ready-marker (fallback ready-marker (lambda () (operating-system-ready-marker defaults)))
|
||||
#:root-authorized-keys (fallback root-authorized-keys (lambda ()
|
||||
(operating-system-root-authorized-keys defaults))))))
|
||||
|
||||
(define (native-build-artifact-entry result artifact-kind)
|
||||
(let* ((artifacts (native-build-result-ref result 'artifacts '()))
|
||||
(entry (assoc artifact-kind artifacts)))
|
||||
@@ -442,25 +710,31 @@
|
||||
(define (native-build-artifact-display-name result artifact-kind)
|
||||
(let* ((base (native-build-result-ref result 'freebsd-base '()))
|
||||
(version-label (native-build-result-ref base 'version-label "unknown"))
|
||||
(executor (native-build-result-ref result 'executor "unknown")))
|
||||
(executor-name (native-build-result-executor-name result)))
|
||||
(string-append "fruix-native-"
|
||||
(symbol->string artifact-kind)
|
||||
"-"
|
||||
version-label
|
||||
"-"
|
||||
executor)))
|
||||
executor-name)))
|
||||
|
||||
(define (native-build-promoted-artifact-metadata result artifact-kind content-signature)
|
||||
(let* ((entry (native-build-artifact-entry result artifact-kind)))
|
||||
(let* ((entry (native-build-artifact-entry result artifact-kind))
|
||||
(executor (native-build-result-executor result))
|
||||
(build-profile (native-build-result-ref result 'build-profile
|
||||
(native-build-result-ref result 'development-profile ""))))
|
||||
`((native-build-object-version . ,native-build-result-promotion-version)
|
||||
(object-kind . artifact)
|
||||
(artifact-kind . ,artifact-kind)
|
||||
(executor . ,(native-build-result-ref result 'executor "unknown"))
|
||||
(executor-version . ,(native-build-result-ref result 'executor-version "unknown"))
|
||||
(executor . ,executor)
|
||||
(executor-kind . ,(native-build-result-executor-kind result))
|
||||
(executor-name . ,(native-build-result-executor-name result))
|
||||
(executor-version . ,(native-build-result-executor-version result))
|
||||
(run-id . ,(native-build-result-ref result 'run-id "unknown"))
|
||||
(guest-host-name . ,(native-build-result-ref result 'guest-host-name "unknown"))
|
||||
(closure-path . ,(native-build-result-ref result 'closure-path ""))
|
||||
(development-profile . ,(native-build-result-ref result 'development-profile ""))
|
||||
(build-profile . ,build-profile)
|
||||
(freebsd-base . ,(native-build-result-ref result 'freebsd-base '()))
|
||||
(source . ,(native-build-result-ref result 'source '()))
|
||||
(build-policy . ,(native-build-result-ref result 'build-policy '()))
|
||||
@@ -494,28 +768,34 @@
|
||||
(define (native-build-result-display-name result)
|
||||
(let* ((base (native-build-result-ref result 'freebsd-base '()))
|
||||
(version-label (native-build-result-ref base 'version-label "unknown"))
|
||||
(executor (native-build-result-ref result 'executor "unknown")))
|
||||
(string-append "fruix-native-build-result-" version-label "-" executor)))
|
||||
(executor-name (native-build-result-executor-name result)))
|
||||
(string-append "fruix-native-build-result-" version-label "-" executor-name)))
|
||||
|
||||
(define (native-build-promoted-result-object result promoted-artifacts)
|
||||
`((native-build-result-version . ,native-build-result-promotion-version)
|
||||
(object-kind . result-bundle)
|
||||
(executor . ,(native-build-result-ref result 'executor "unknown"))
|
||||
(executor-version . ,(native-build-result-ref result 'executor-version "unknown"))
|
||||
(run-id . ,(native-build-result-ref result 'run-id "unknown"))
|
||||
(guest-host-name . ,(native-build-result-ref result 'guest-host-name "unknown"))
|
||||
(closure-path . ,(native-build-result-ref result 'closure-path ""))
|
||||
(development-profile . ,(native-build-result-ref result 'development-profile ""))
|
||||
(freebsd-base . ,(native-build-result-ref result 'freebsd-base '()))
|
||||
(source . ,(native-build-result-ref result 'source '()))
|
||||
(build-policy . ,(native-build-result-ref result 'build-policy '()))
|
||||
(artifact-count . ,(length promoted-artifacts))
|
||||
(artifacts . ,(map (lambda (entry)
|
||||
`((artifact-kind . ,(assoc-ref entry 'artifact-kind))
|
||||
(store-path . ,(assoc-ref entry 'store-path))
|
||||
(content-signature . ,(assoc-ref entry 'content-signature))
|
||||
(metadata-file . ,(assoc-ref entry 'metadata-file))))
|
||||
promoted-artifacts))))
|
||||
(let ((executor (native-build-result-executor result))
|
||||
(build-profile (native-build-result-ref result 'build-profile
|
||||
(native-build-result-ref result 'development-profile ""))))
|
||||
`((native-build-result-version . ,native-build-result-promotion-version)
|
||||
(object-kind . result-bundle)
|
||||
(executor . ,executor)
|
||||
(executor-kind . ,(native-build-result-executor-kind result))
|
||||
(executor-name . ,(native-build-result-executor-name result))
|
||||
(executor-version . ,(native-build-result-executor-version result))
|
||||
(run-id . ,(native-build-result-ref result 'run-id "unknown"))
|
||||
(guest-host-name . ,(native-build-result-ref result 'guest-host-name "unknown"))
|
||||
(closure-path . ,(native-build-result-ref result 'closure-path ""))
|
||||
(development-profile . ,(native-build-result-ref result 'development-profile ""))
|
||||
(build-profile . ,build-profile)
|
||||
(freebsd-base . ,(native-build-result-ref result 'freebsd-base '()))
|
||||
(source . ,(native-build-result-ref result 'source '()))
|
||||
(build-policy . ,(native-build-result-ref result 'build-policy '()))
|
||||
(artifact-count . ,(length promoted-artifacts))
|
||||
(artifacts . ,(map (lambda (entry)
|
||||
`((artifact-kind . ,(assoc-ref entry 'artifact-kind))
|
||||
(store-path . ,(assoc-ref entry 'store-path))
|
||||
(content-signature . ,(assoc-ref entry 'content-signature))
|
||||
(metadata-file . ,(assoc-ref entry 'metadata-file))))
|
||||
promoted-artifacts)))))
|
||||
|
||||
(define* (promote-native-build-result result-root #:key (store-dir "/frx/store"))
|
||||
(let* ((result (read-native-build-result result-root))
|
||||
@@ -544,6 +824,9 @@
|
||||
(write-file (string-append result-store "/.fruix-native-build-result.scm")
|
||||
payload))
|
||||
`((result-root . ,result-root)
|
||||
(executor-kind . ,(native-build-result-executor-kind result))
|
||||
(executor-name . ,(native-build-result-executor-name result))
|
||||
(executor-version . ,(native-build-result-executor-version result))
|
||||
(result-store . ,result-store)
|
||||
(result-metadata-file . ,(string-append result-store "/.fruix-native-build-result.scm"))
|
||||
(artifact-store-count . ,(length promoted-artifacts))
|
||||
|
||||
121
modules/fruix/system/freebsd/executor.scm
Normal file
121
modules/fruix/system/freebsd/executor.scm
Normal file
@@ -0,0 +1,121 @@
|
||||
(define-module (fruix system freebsd executor)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:export (native-build-executor-model-version
|
||||
native-build-executor
|
||||
native-build-executor?
|
||||
native-build-executor-ref
|
||||
native-build-executor-kind
|
||||
native-build-executor-name
|
||||
native-build-executor-version
|
||||
native-build-executor-properties
|
||||
normalize-native-build-executor
|
||||
host-native-build-executor
|
||||
ssh-guest-native-build-executor
|
||||
self-hosted-native-build-executor))
|
||||
|
||||
(define native-build-executor-model-version "1")
|
||||
|
||||
(define (association-list? value)
|
||||
(and (list? value)
|
||||
(every pair? value)))
|
||||
|
||||
(define (executor-name kind provided-name)
|
||||
(or provided-name
|
||||
(symbol->string kind)))
|
||||
|
||||
(define* (native-build-executor #:key kind name
|
||||
(version native-build-executor-model-version)
|
||||
(properties '()))
|
||||
(unless (symbol? kind)
|
||||
(error "native build executor kind must be a symbol" kind))
|
||||
(unless (string? (executor-name kind name))
|
||||
(error "native build executor name must be a string" name))
|
||||
(unless (string? version)
|
||||
(error "native build executor version must be a string" version))
|
||||
(unless (association-list? properties)
|
||||
(error "native build executor properties must be an association list" properties))
|
||||
`((kind . ,kind)
|
||||
(name . ,(executor-name kind name))
|
||||
(version . ,version)
|
||||
(properties . ,properties)))
|
||||
|
||||
(define (native-build-executor-ref executor key default)
|
||||
(match (assoc key executor)
|
||||
((_ . value) value)
|
||||
(#f default)))
|
||||
|
||||
(define (native-build-executor? value)
|
||||
(and (association-list? value)
|
||||
(symbol? (native-build-executor-ref value 'kind #f))
|
||||
(string? (native-build-executor-ref value 'name #f))
|
||||
(string? (native-build-executor-ref value 'version #f))
|
||||
(association-list? (native-build-executor-ref value 'properties '()))))
|
||||
|
||||
(define (native-build-executor-kind executor)
|
||||
(native-build-executor-ref executor 'kind 'unknown))
|
||||
|
||||
(define (native-build-executor-name executor)
|
||||
(native-build-executor-ref executor 'name "unknown"))
|
||||
|
||||
(define (native-build-executor-version executor)
|
||||
(native-build-executor-ref executor 'version "unknown"))
|
||||
|
||||
(define (native-build-executor-properties executor)
|
||||
(native-build-executor-ref executor 'properties '()))
|
||||
|
||||
(define (legacy-executor-kind name)
|
||||
(cond
|
||||
((member name '("host")) 'host)
|
||||
((member name '("ssh-guest" "guest-ssh" "guest-host-initiated")) 'ssh-guest)
|
||||
((member name '("self-hosted" "guest-self-hosted")) 'self-hosted)
|
||||
((member name '("jail")) 'jail)
|
||||
((member name '("remote-builder")) 'remote-builder)
|
||||
(else 'legacy)))
|
||||
|
||||
(define (normalize-native-build-executor value)
|
||||
(cond
|
||||
((native-build-executor? value)
|
||||
value)
|
||||
((string? value)
|
||||
(native-build-executor #:kind (legacy-executor-kind value)
|
||||
#:name value
|
||||
#:version "legacy"))
|
||||
(else
|
||||
(error "unsupported native build executor representation" value))))
|
||||
|
||||
(define* (host-native-build-executor #:key (name "host")
|
||||
host-name working-directory)
|
||||
(native-build-executor
|
||||
#:kind 'host
|
||||
#:name name
|
||||
#:properties (filter-map identity
|
||||
`((host-name . ,host-name)
|
||||
(working-directory . ,working-directory)))))
|
||||
|
||||
(define* (ssh-guest-native-build-executor #:key (name "ssh-guest")
|
||||
transport orchestrator
|
||||
guest-host-name guest-ip vm-id vdi-id)
|
||||
(native-build-executor
|
||||
#:kind 'ssh-guest
|
||||
#:name name
|
||||
#:properties (filter-map identity
|
||||
`((transport . ,(or transport "ssh"))
|
||||
(orchestrator . ,(or orchestrator "host"))
|
||||
(guest-host-name . ,guest-host-name)
|
||||
(guest-ip . ,guest-ip)
|
||||
(vm-id . ,vm-id)
|
||||
(vdi-id . ,vdi-id)))))
|
||||
|
||||
(define* (self-hosted-native-build-executor #:key (name "self-hosted")
|
||||
helper-path helper-version
|
||||
guest-host-name build-root-base result-root-base)
|
||||
(native-build-executor
|
||||
#:kind 'self-hosted
|
||||
#:name name
|
||||
#:version (or helper-version native-build-executor-model-version)
|
||||
#:properties (filter-map identity
|
||||
`((helper-path . ,helper-path)
|
||||
(guest-host-name . ,guest-host-name)
|
||||
(build-root-base . ,build-root-base)
|
||||
(result-root-base . ,result-root-base)))))
|
||||
@@ -72,14 +72,22 @@
|
||||
(store-dir "/frx/store")
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install"))
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(guile-store-path #f)
|
||||
(guile-extra-store-path #f)
|
||||
(shepherd-store-path #f)
|
||||
(declaration-source #f)
|
||||
(declaration-origin #f)
|
||||
(declaration-system-symbol #f))
|
||||
(validate-operating-system os)
|
||||
(let* ((cache (make-hash-table))
|
||||
(source-cache (make-hash-table))
|
||||
(native-build-result (operating-system-native-build-result os))
|
||||
(kernel-package (operating-system-kernel os))
|
||||
(bootloader-package (operating-system-bootloader os))
|
||||
(base-packages (operating-system-base-packages os))
|
||||
(development-packages (operating-system-development-packages os))
|
||||
(build-packages (operating-system-build-packages os))
|
||||
(kernel-store (materialize-freebsd-package kernel-package store-dir cache source-cache))
|
||||
(bootloader-store (materialize-freebsd-package bootloader-package store-dir cache source-cache))
|
||||
(base-package-stores (map (lambda (package)
|
||||
@@ -89,6 +97,10 @@
|
||||
(map (lambda (package)
|
||||
(materialize-freebsd-package package store-dir cache source-cache))
|
||||
development-packages))
|
||||
(build-package-stores
|
||||
(map (lambda (package)
|
||||
(materialize-freebsd-package package store-dir cache source-cache))
|
||||
build-packages))
|
||||
(base-package-pairs (map cons base-packages base-package-stores))
|
||||
(store-classification
|
||||
(append (list (cons kernel-package kernel-store)
|
||||
@@ -109,12 +121,15 @@
|
||||
("/usr/local/lib/libtasn1.so.6" . "lib/libtasn1.so.6")
|
||||
("/usr/local/lib/libhogweed.so.6" . "lib/libhogweed.so.6")
|
||||
("/usr/local/lib/libnettle.so.8" . "lib/libnettle.so.8")))
|
||||
(guile-store (materialize-prefix guile-prefix "fruix-guile-runtime" "3.0" store-dir
|
||||
#:extra-files guile-runtime-extra-files))
|
||||
(guile-extra-store (materialize-prefix guile-extra-prefix "fruix-guile-extra" "3.0" store-dir
|
||||
#:extra-files (append guile-runtime-extra-files
|
||||
guile-extra-runtime-files)))
|
||||
(shepherd-store (materialize-prefix shepherd-prefix "fruix-shepherd-runtime" "1.0.9" store-dir))
|
||||
(guile-store (or guile-store-path
|
||||
(materialize-prefix guile-prefix "fruix-guile-runtime" "3.0" store-dir
|
||||
#:extra-files guile-runtime-extra-files)))
|
||||
(guile-extra-store (or guile-extra-store-path
|
||||
(materialize-prefix guile-extra-prefix "fruix-guile-extra" "3.0" store-dir
|
||||
#:extra-files (append guile-runtime-extra-files
|
||||
guile-extra-runtime-files))))
|
||||
(shepherd-store (or shepherd-store-path
|
||||
(materialize-prefix shepherd-prefix "fruix-shepherd-runtime" "1.0.9" store-dir)))
|
||||
(host-base-stores
|
||||
(delete-duplicates
|
||||
(map cdr
|
||||
@@ -134,31 +149,76 @@
|
||||
(delete-duplicates (map (lambda (result)
|
||||
(assoc-ref result 'source-store-path))
|
||||
source-materializations)))
|
||||
(promoted-native-build-result-summary
|
||||
(and native-build-result
|
||||
(promoted-native-build-result-spec native-build-result)))
|
||||
(promoted-native-build-result-store
|
||||
(and native-build-result
|
||||
(promoted-native-build-result-store-path native-build-result)))
|
||||
(promoted-native-build-artifact-stores
|
||||
(delete-duplicates
|
||||
(filter identity
|
||||
(if native-build-result
|
||||
(map (lambda (artifact-kind)
|
||||
(promoted-native-build-result-artifact-store native-build-result artifact-kind))
|
||||
'(world kernel headers bootloader))
|
||||
'()))))
|
||||
(declaration-source-text
|
||||
(or declaration-source
|
||||
";; Fruix declaration source is unavailable for this closure.\n"))
|
||||
(declaration-origin-text (or declaration-origin ""))
|
||||
(declaration-system-text
|
||||
(cond ((symbol? declaration-system-symbol)
|
||||
(symbol->string declaration-system-symbol))
|
||||
((string? declaration-system-symbol)
|
||||
declaration-system-symbol)
|
||||
(else "")))
|
||||
(declaration-info-object
|
||||
`((available? . ,(not (not declaration-source)))
|
||||
(system-variable . ,declaration-system-text)))
|
||||
(metadata-files
|
||||
`(("metadata/freebsd-base.scm"
|
||||
. ,(object->string (freebsd-base-spec (operating-system-freebsd-base os))))
|
||||
("metadata/freebsd-source.scm"
|
||||
. ,(object->string (freebsd-source-spec (freebsd-base-source (operating-system-freebsd-base os)))))
|
||||
("metadata/freebsd-source-materializations.scm"
|
||||
. ,(object->string (map freebsd-source-materialization-spec source-materializations)))
|
||||
("metadata/host-base-provenance.scm"
|
||||
. ,(object->string (host-freebsd-provenance)))
|
||||
("metadata/store-layout.scm"
|
||||
. ,(object->string
|
||||
`((freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
|
||||
(freebsd-source . ,(freebsd-source-spec (freebsd-base-source (operating-system-freebsd-base os))))
|
||||
(materialized-source-store-count . ,(length materialized-source-stores))
|
||||
(materialized-source-stores . ,materialized-source-stores)
|
||||
(host-base-store-count . ,(length host-base-stores))
|
||||
(host-base-stores . ,host-base-stores)
|
||||
(native-base-store-count . ,(length native-base-stores))
|
||||
(native-base-stores . ,native-base-stores)
|
||||
(development-package-store-count . ,(length development-package-stores))
|
||||
(development-package-stores . ,development-package-stores)
|
||||
(fruix-runtime-store-count . ,(length fruix-runtime-stores))
|
||||
(fruix-runtime-stores . ,fruix-runtime-stores)
|
||||
(host-base-replacement-order . ,%freebsd-host-staged-replacement-order)
|
||||
(init-mode . ,(operating-system-init-mode os)))))))
|
||||
(append
|
||||
(list (cons "metadata/freebsd-base.scm"
|
||||
(object->string (freebsd-base-spec (operating-system-freebsd-base os))))
|
||||
(cons "metadata/freebsd-source.scm"
|
||||
(object->string (freebsd-source-spec (freebsd-base-source (operating-system-freebsd-base os)))))
|
||||
(cons "metadata/freebsd-source-materializations.scm"
|
||||
(object->string (map freebsd-source-materialization-spec source-materializations)))
|
||||
(cons "metadata/host-base-provenance.scm"
|
||||
(object->string (host-freebsd-provenance)))
|
||||
(cons "metadata/system-declaration.scm"
|
||||
declaration-source-text)
|
||||
(cons "metadata/system-declaration-info.scm"
|
||||
(object->string declaration-info-object))
|
||||
(cons "metadata/system-declaration-system"
|
||||
(string-append declaration-system-text "\n"))
|
||||
(cons "metadata/store-layout.scm"
|
||||
(object->string
|
||||
`((freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
|
||||
(freebsd-source . ,(freebsd-source-spec (freebsd-base-source (operating-system-freebsd-base os))))
|
||||
(system-declaration-available? . ,(not (not declaration-source)))
|
||||
(system-declaration-system-variable . ,declaration-system-text)
|
||||
(promoted-native-build-result . ,promoted-native-build-result-summary)
|
||||
(promoted-native-build-artifact-store-count . ,(length promoted-native-build-artifact-stores))
|
||||
(promoted-native-build-artifact-stores . ,promoted-native-build-artifact-stores)
|
||||
(materialized-source-store-count . ,(length materialized-source-stores))
|
||||
(materialized-source-stores . ,materialized-source-stores)
|
||||
(host-base-store-count . ,(length host-base-stores))
|
||||
(host-base-stores . ,host-base-stores)
|
||||
(native-base-store-count . ,(length native-base-stores))
|
||||
(native-base-stores . ,native-base-stores)
|
||||
(development-package-store-count . ,(length development-package-stores))
|
||||
(development-package-stores . ,development-package-stores)
|
||||
(build-package-store-count . ,(length build-package-stores))
|
||||
(build-package-stores . ,build-package-stores)
|
||||
(fruix-runtime-store-count . ,(length fruix-runtime-stores))
|
||||
(fruix-runtime-stores . ,fruix-runtime-stores)
|
||||
(host-base-replacement-order . ,%freebsd-host-staged-replacement-order)
|
||||
(init-mode . ,(operating-system-init-mode os))))))
|
||||
(if promoted-native-build-result-summary
|
||||
(list (cons "metadata/promoted-native-build-result.scm"
|
||||
(object->string promoted-native-build-result-summary)))
|
||||
'())))
|
||||
(generated-files (append (operating-system-generated-files os
|
||||
#:guile-store guile-store
|
||||
#:guile-extra-store guile-extra-store
|
||||
@@ -169,10 +229,14 @@
|
||||
("usr/local/etc/rc.d/fruix-shepherd"
|
||||
. ,(render-rc-script shepherd-store guile-store guile-extra-store)))))
|
||||
(references (delete-duplicates
|
||||
(append materialized-source-stores
|
||||
(append (if promoted-native-build-result-store
|
||||
(list promoted-native-build-result-store)
|
||||
'())
|
||||
materialized-source-stores
|
||||
host-base-stores
|
||||
native-base-stores
|
||||
development-package-stores
|
||||
build-package-stores
|
||||
fruix-runtime-stores)))
|
||||
(manifest (string-append
|
||||
"closure-spec=\n"
|
||||
@@ -189,7 +253,9 @@
|
||||
(closure-path (make-store-path store-dir display-name manifest
|
||||
#:kind 'operating-system))
|
||||
(development-profile-path (and (not (null? development-package-stores))
|
||||
(string-append closure-path "/development-profile"))))
|
||||
(string-append closure-path "/development-profile")))
|
||||
(build-profile-path (and (not (null? build-package-stores))
|
||||
(string-append closure-path "/build-profile"))))
|
||||
(unless (file-exists? closure-path)
|
||||
(mkdir-p closure-path)
|
||||
(mkdir-p (string-append closure-path "/boot/kernel"))
|
||||
@@ -212,6 +278,11 @@
|
||||
(for-each (lambda (output)
|
||||
(merge-output-into-tree output development-profile-path))
|
||||
development-package-stores))
|
||||
(when build-profile-path
|
||||
(mkdir-p build-profile-path)
|
||||
(for-each (lambda (output)
|
||||
(merge-output-into-tree output build-profile-path))
|
||||
build-package-stores))
|
||||
(for-each
|
||||
(lambda (entry)
|
||||
(write-file (string-append closure-path "/" (car entry)) (cdr entry)))
|
||||
@@ -225,6 +296,8 @@
|
||||
(chmod (string-append closure-path "/usr/local/bin/fruix") #o555))
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-development-environment"))
|
||||
(chmod (string-append closure-path "/usr/local/bin/fruix-development-environment") #o555))
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-build-environment"))
|
||||
(chmod (string-append closure-path "/usr/local/bin/fruix-build-environment") #o555))
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-self-hosted-native-build"))
|
||||
(chmod (string-append closure-path "/usr/local/bin/fruix-self-hosted-native-build") #o555))
|
||||
(when (file-exists? (string-append closure-path "/boot/fruix-pid1"))
|
||||
@@ -242,7 +315,9 @@
|
||||
(shepherd-store . ,shepherd-store)
|
||||
(base-package-stores . ,base-package-stores)
|
||||
(development-package-stores . ,development-package-stores)
|
||||
(build-package-stores . ,build-package-stores)
|
||||
(development-profile-path . ,development-profile-path)
|
||||
(build-profile-path . ,build-profile-path)
|
||||
(host-base-stores . ,host-base-stores)
|
||||
(native-base-stores . ,native-base-stores)
|
||||
(fruix-runtime-stores . ,fruix-runtime-stores)
|
||||
@@ -251,7 +326,13 @@
|
||||
(freebsd-source-materializations-file . ,(string-append closure-path "/metadata/freebsd-source-materializations.scm"))
|
||||
(materialized-source-stores . ,materialized-source-stores)
|
||||
(host-base-provenance-file . ,(string-append closure-path "/metadata/host-base-provenance.scm"))
|
||||
(system-declaration-file . ,(string-append closure-path "/metadata/system-declaration.scm"))
|
||||
(system-declaration-info-file . ,(string-append closure-path "/metadata/system-declaration-info.scm"))
|
||||
(system-declaration-system-file . ,(string-append closure-path "/metadata/system-declaration-system"))
|
||||
(store-layout-file . ,(string-append closure-path "/metadata/store-layout.scm"))
|
||||
(promoted-native-build-result-file
|
||||
. ,(and promoted-native-build-result-summary
|
||||
(string-append closure-path "/metadata/promoted-native-build-result.scm")))
|
||||
(generated-files . ,(map car generated-files))
|
||||
(references . ,references))))
|
||||
|
||||
@@ -280,6 +361,9 @@
|
||||
(freebsd-source-materializations-file
|
||||
. ,(string-append closure-path "/metadata/freebsd-source-materializations.scm"))
|
||||
(host-base-provenance-file . ,(string-append closure-path "/metadata/host-base-provenance.scm"))
|
||||
(system-declaration-file . ,(string-append closure-path "/metadata/system-declaration.scm"))
|
||||
(system-declaration-info-file . ,(string-append closure-path "/metadata/system-declaration-info.scm"))
|
||||
(system-declaration-system-file . ,(string-append closure-path "/metadata/system-declaration-system"))
|
||||
(store-layout-file . ,(string-append closure-path "/metadata/store-layout.scm"))
|
||||
(install-metadata-path . ,install-metadata-path)
|
||||
(install-spec . ,install-spec)))
|
||||
@@ -292,6 +376,9 @@
|
||||
(freebsd-source-materializations-file
|
||||
. ,(string-append closure-path "/metadata/freebsd-source-materializations.scm"))
|
||||
(host-base-provenance-file . ,(string-append closure-path "/metadata/host-base-provenance.scm"))
|
||||
(system-declaration-file . ,(string-append closure-path "/metadata/system-declaration.scm"))
|
||||
(system-declaration-info-file . ,(string-append closure-path "/metadata/system-declaration-info.scm"))
|
||||
(system-declaration-system-file . ,(string-append closure-path "/metadata/system-declaration-system"))
|
||||
(store-layout-file . ,(string-append closure-path "/metadata/store-layout.scm"))))
|
||||
|
||||
(define* (populate-system-generation-layout os rootfs closure-path
|
||||
@@ -378,7 +465,18 @@
|
||||
(string-append rootfs "/usr/local/bin/fruix"))
|
||||
(when (file-exists? (string-append closure-path "/development-profile"))
|
||||
(symlink-force "/run/current-system/development-profile"
|
||||
(string-append rootfs "/run/current-development"))
|
||||
(string-append rootfs "/run/current-development")))
|
||||
(when (file-exists? (string-append closure-path "/build-profile"))
|
||||
(symlink-force "/run/current-system/build-profile"
|
||||
(string-append rootfs "/run/current-build"))
|
||||
(when (file-exists? (string-append closure-path "/build-profile/usr/include"))
|
||||
(symlink-force "/run/current-system/build-profile/usr/include"
|
||||
(string-append rootfs "/usr/include")))
|
||||
(when (file-exists? (string-append closure-path "/build-profile/usr/share/mk"))
|
||||
(symlink-force "/run/current-system/build-profile/usr/share/mk"
|
||||
(string-append rootfs "/usr/share/mk"))))
|
||||
(when (and (not (file-exists? (string-append closure-path "/build-profile")))
|
||||
(file-exists? (string-append closure-path "/development-profile")))
|
||||
(when (file-exists? (string-append closure-path "/development-profile/usr/include"))
|
||||
(symlink-force "/run/current-system/development-profile/usr/include"
|
||||
(string-append rootfs "/usr/include")))
|
||||
@@ -388,6 +486,9 @@
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-development-environment"))
|
||||
(symlink-force "/run/current-system/usr/local/bin/fruix-development-environment"
|
||||
(string-append rootfs "/usr/local/bin/fruix-development-environment")))
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-build-environment"))
|
||||
(symlink-force "/run/current-system/usr/local/bin/fruix-build-environment"
|
||||
(string-append rootfs "/usr/local/bin/fruix-build-environment")))
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-self-hosted-native-build"))
|
||||
(symlink-force "/run/current-system/usr/local/bin/fruix-self-hosted-native-build"
|
||||
(string-append rootfs "/usr/local/bin/fruix-self-hosted-native-build")))
|
||||
@@ -408,12 +509,18 @@
|
||||
(store-dir "/frx/store")
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install"))
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(declaration-source #f)
|
||||
(declaration-origin #f)
|
||||
(declaration-system-symbol #f))
|
||||
(let* ((closure (materialize-operating-system os
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(closure-path (assoc-ref closure 'closure-path)))
|
||||
(populate-rootfs-from-closure os rootfs closure-path)))
|
||||
|
||||
@@ -754,6 +861,9 @@
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(declaration-source #f)
|
||||
(declaration-origin #f)
|
||||
(declaration-system-symbol #f)
|
||||
(efi-size "64m")
|
||||
(root-size #f)
|
||||
(disk-capacity #f)
|
||||
@@ -766,7 +876,10 @@
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(closure-path (assoc-ref closure 'closure-path))
|
||||
(store-items (store-reference-closure (list closure-path)))
|
||||
(target-kind (if (string-prefix? "/dev/" target)
|
||||
@@ -881,6 +994,9 @@
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(declaration-source #f)
|
||||
(declaration-origin #f)
|
||||
(declaration-system-symbol #f)
|
||||
(efi-size "64m")
|
||||
(root-size "256m")
|
||||
(disk-capacity #f)
|
||||
@@ -891,7 +1007,10 @@
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(closure-path (assoc-ref closure 'closure-path))
|
||||
(image-spec (operating-system-image-spec os
|
||||
#:efi-size efi-size
|
||||
@@ -934,7 +1053,10 @@
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix)
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol)
|
||||
(copy-rootfs-for-image rootfs image-rootfs)
|
||||
(copy-store-items-into-rootfs image-rootfs store-dir store-items)
|
||||
(mkdir-p (string-append esp-stage "/EFI/BOOT"))
|
||||
@@ -1002,6 +1124,9 @@
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(declaration-source #f)
|
||||
(declaration-origin #f)
|
||||
(declaration-system-symbol #f)
|
||||
(install-target-device "/dev/vtbd1")
|
||||
(efi-size "64m")
|
||||
(root-size "10g")
|
||||
@@ -1020,12 +1145,18 @@
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(installer-closure (materialize-operating-system installer-os
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(target-closure-path (assoc-ref target-closure 'closure-path))
|
||||
(installer-closure-path (assoc-ref installer-closure 'closure-path))
|
||||
(target-store-items (store-reference-closure (list target-closure-path)))
|
||||
@@ -1310,6 +1441,9 @@
|
||||
(guile-prefix "/tmp/guile-freebsd-validate-install")
|
||||
(guile-extra-prefix "/tmp/guile-gnutls-freebsd-validate-install")
|
||||
(shepherd-prefix "/tmp/shepherd-freebsd-validate-install")
|
||||
(declaration-source #f)
|
||||
(declaration-origin #f)
|
||||
(declaration-system-symbol #f)
|
||||
(install-target-device "/dev/vtbd0")
|
||||
(root-size #f)
|
||||
(installer-host-name (string-append (operating-system-host-name os)
|
||||
@@ -1326,12 +1460,18 @@
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(installer-closure (materialize-operating-system installer-os
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin declaration-origin
|
||||
#:declaration-system-symbol declaration-system-symbol))
|
||||
(target-closure-path (assoc-ref target-closure 'closure-path))
|
||||
(installer-closure-path (assoc-ref installer-closure 'closure-path))
|
||||
(target-closure-store-items (store-reference-closure (list target-closure-path)))
|
||||
|
||||
@@ -26,14 +26,22 @@
|
||||
file-system-type
|
||||
file-system-options
|
||||
file-system-needed-for-boot?
|
||||
make-promoted-native-build-result
|
||||
promoted-native-build-result?
|
||||
promoted-native-build-result-store-path
|
||||
promoted-native-build-result-metadata-file
|
||||
promoted-native-build-result-metadata
|
||||
promoted-native-build-result-spec
|
||||
operating-system
|
||||
operating-system?
|
||||
operating-system-host-name
|
||||
operating-system-freebsd-base
|
||||
operating-system-native-build-result
|
||||
operating-system-kernel
|
||||
operating-system-bootloader
|
||||
operating-system-base-packages
|
||||
operating-system-development-packages
|
||||
operating-system-build-packages
|
||||
operating-system-users
|
||||
operating-system-groups
|
||||
operating-system-file-systems
|
||||
@@ -95,17 +103,71 @@
|
||||
(needed-for-boot? #f))
|
||||
(make-file-system device mount-point type options needed-for-boot?))
|
||||
|
||||
(define-record-type <promoted-native-build-result>
|
||||
(make-promoted-native-build-result store-path metadata-file metadata)
|
||||
promoted-native-build-result?
|
||||
(store-path promoted-native-build-result-store-path)
|
||||
(metadata-file promoted-native-build-result-metadata-file)
|
||||
(metadata promoted-native-build-result-metadata))
|
||||
|
||||
(define (promoted-native-build-result-metadata-ref metadata key default)
|
||||
(match (assoc key metadata)
|
||||
((_ . value) value)
|
||||
(#f default)))
|
||||
|
||||
(define (promoted-native-build-result-artifact-spec metadata artifact-kind)
|
||||
(find (lambda (entry)
|
||||
(eq? (promoted-native-build-result-metadata-ref entry 'artifact-kind #f)
|
||||
artifact-kind))
|
||||
(promoted-native-build-result-metadata-ref metadata 'artifacts '())))
|
||||
|
||||
(define (promoted-native-build-result-spec result)
|
||||
(let* ((metadata (promoted-native-build-result-metadata result))
|
||||
(base (promoted-native-build-result-metadata-ref metadata 'freebsd-base '()))
|
||||
(source (promoted-native-build-result-metadata-ref metadata 'source '())))
|
||||
`((store-path . ,(promoted-native-build-result-store-path result))
|
||||
(metadata-file . ,(promoted-native-build-result-metadata-file result))
|
||||
(executor-kind . ,(promoted-native-build-result-metadata-ref metadata 'executor-kind #f))
|
||||
(executor-name . ,(promoted-native-build-result-metadata-ref metadata 'executor-name #f))
|
||||
(executor-version . ,(promoted-native-build-result-metadata-ref metadata 'executor-version #f))
|
||||
(run-id . ,(promoted-native-build-result-metadata-ref metadata 'run-id #f))
|
||||
(version-label . ,(promoted-native-build-result-metadata-ref base 'version-label #f))
|
||||
(release . ,(promoted-native-build-result-metadata-ref base 'release #f))
|
||||
(branch . ,(promoted-native-build-result-metadata-ref base 'branch #f))
|
||||
(source-store . ,(promoted-native-build-result-metadata-ref source 'store-path #f))
|
||||
(source-root . ,(promoted-native-build-result-metadata-ref source 'source-root #f))
|
||||
(artifact-count . ,(promoted-native-build-result-metadata-ref metadata 'artifact-count 0))
|
||||
(world-store . ,(promoted-native-build-result-metadata-ref
|
||||
(promoted-native-build-result-artifact-spec metadata 'world)
|
||||
'store-path
|
||||
#f))
|
||||
(kernel-store . ,(promoted-native-build-result-metadata-ref
|
||||
(promoted-native-build-result-artifact-spec metadata 'kernel)
|
||||
'store-path
|
||||
#f))
|
||||
(headers-store . ,(promoted-native-build-result-metadata-ref
|
||||
(promoted-native-build-result-artifact-spec metadata 'headers)
|
||||
'store-path
|
||||
#f))
|
||||
(bootloader-store . ,(promoted-native-build-result-metadata-ref
|
||||
(promoted-native-build-result-artifact-spec metadata 'bootloader)
|
||||
'store-path
|
||||
#f)))))
|
||||
|
||||
(define-record-type <operating-system>
|
||||
(make-operating-system host-name freebsd-base kernel bootloader base-packages development-packages
|
||||
users groups file-systems services loader-entries rc-conf-entries
|
||||
init-mode ready-marker root-authorized-keys)
|
||||
(make-operating-system host-name freebsd-base native-build-result kernel bootloader
|
||||
base-packages development-packages build-packages users groups file-systems
|
||||
services loader-entries rc-conf-entries init-mode ready-marker
|
||||
root-authorized-keys)
|
||||
operating-system?
|
||||
(host-name operating-system-host-name)
|
||||
(freebsd-base operating-system-freebsd-base)
|
||||
(native-build-result operating-system-native-build-result)
|
||||
(kernel operating-system-kernel)
|
||||
(bootloader operating-system-bootloader)
|
||||
(base-packages operating-system-base-packages)
|
||||
(development-packages operating-system-development-packages)
|
||||
(build-packages operating-system-build-packages)
|
||||
(users operating-system-users)
|
||||
(groups operating-system-groups)
|
||||
(file-systems operating-system-file-systems)
|
||||
@@ -119,10 +181,12 @@
|
||||
(define* (operating-system #:key
|
||||
(host-name "fruix-freebsd")
|
||||
(freebsd-base %default-freebsd-base)
|
||||
(native-build-result #f)
|
||||
(kernel freebsd-kernel)
|
||||
(bootloader freebsd-bootloader)
|
||||
(base-packages %freebsd-system-packages)
|
||||
(development-packages '())
|
||||
(build-packages '())
|
||||
(users (list (user-account #:name "root"
|
||||
#:uid 0
|
||||
#:group "wheel"
|
||||
@@ -164,9 +228,10 @@
|
||||
(init-mode 'freebsd-init+rc.d-shepherd)
|
||||
(ready-marker "/var/lib/fruix/ready")
|
||||
(root-authorized-keys '()))
|
||||
(make-operating-system host-name freebsd-base kernel bootloader base-packages development-packages
|
||||
users groups file-systems services loader-entries rc-conf-entries
|
||||
init-mode ready-marker root-authorized-keys))
|
||||
(make-operating-system host-name freebsd-base native-build-result kernel bootloader
|
||||
base-packages development-packages build-packages users groups file-systems
|
||||
services loader-entries rc-conf-entries init-mode ready-marker
|
||||
root-authorized-keys))
|
||||
|
||||
(define default-minimal-operating-system (operating-system))
|
||||
|
||||
@@ -234,8 +299,10 @@
|
||||
(define (validate-operating-system os)
|
||||
(let* ((host-name (operating-system-host-name os))
|
||||
(base (operating-system-freebsd-base os))
|
||||
(native-build-result (operating-system-native-build-result os))
|
||||
(base-packages (operating-system-base-packages os))
|
||||
(development-packages (operating-system-development-packages os))
|
||||
(build-packages (operating-system-build-packages os))
|
||||
(users (operating-system-users os))
|
||||
(groups (operating-system-groups os))
|
||||
(file-systems (operating-system-file-systems os))
|
||||
@@ -247,10 +314,15 @@
|
||||
(error "operating-system host-name must not be empty"))
|
||||
(unless (freebsd-base? base)
|
||||
(error "operating-system freebsd-base must be a <freebsd-base> record"))
|
||||
(when native-build-result
|
||||
(unless (promoted-native-build-result? native-build-result)
|
||||
(error "operating-system native-build-result must be a <promoted-native-build-result> record")))
|
||||
(unless (every freebsd-package? base-packages)
|
||||
(error "operating-system base-packages must be a list of <freebsd-package> records"))
|
||||
(unless (every freebsd-package? development-packages)
|
||||
(error "operating-system development-packages must be a list of <freebsd-package> records"))
|
||||
(unless (every freebsd-package? build-packages)
|
||||
(error "operating-system build-packages must be a list of <freebsd-package> records"))
|
||||
(validate-freebsd-source (freebsd-base-source base))
|
||||
(let ((dups (duplicate-elements user-names)))
|
||||
(unless (null? dups)
|
||||
@@ -303,12 +375,22 @@
|
||||
"metadata/freebsd-base.scm"
|
||||
"metadata/host-base-provenance.scm"
|
||||
"metadata/store-layout.scm"
|
||||
"metadata/system-declaration.scm"
|
||||
"metadata/system-declaration-info.scm"
|
||||
"metadata/system-declaration-system"
|
||||
"activate"
|
||||
"shepherd/init.scm"
|
||||
"share/fruix/node/scripts/fruix.scm"
|
||||
"usr/local/bin/fruix")
|
||||
(if (operating-system-native-build-result os)
|
||||
'("metadata/promoted-native-build-result.scm")
|
||||
'())
|
||||
(if (null? (operating-system-development-packages os))
|
||||
'()
|
||||
'("usr/local/bin/fruix-development-environment"
|
||||
'("usr/local/bin/fruix-development-environment"))
|
||||
(if (null? (operating-system-build-packages os))
|
||||
'()
|
||||
'("usr/local/bin/fruix-build-environment"
|
||||
"usr/local/bin/fruix-self-hosted-native-build"))
|
||||
(if (pid1-init-mode? os)
|
||||
'("boot/fruix-pid1")
|
||||
@@ -325,16 +407,26 @@
|
||||
(validate-operating-system os)
|
||||
`((host-name . ,(operating-system-host-name os))
|
||||
(freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
|
||||
(promoted-native-build-result
|
||||
. ,(and (operating-system-native-build-result os)
|
||||
(promoted-native-build-result-spec
|
||||
(operating-system-native-build-result os))))
|
||||
(kernel-package . ,(freebsd-package-name (operating-system-kernel os)))
|
||||
(bootloader-package . ,(freebsd-package-name (operating-system-bootloader os)))
|
||||
(base-package-count . ,(length (operating-system-base-packages os)))
|
||||
(base-packages . ,(package-names (operating-system-base-packages os)))
|
||||
(development-package-count . ,(length (operating-system-development-packages os)))
|
||||
(development-packages . ,(package-names (operating-system-development-packages os)))
|
||||
(build-package-count . ,(length (operating-system-build-packages os)))
|
||||
(build-packages . ,(package-names (operating-system-build-packages os)))
|
||||
(installed-system-command-surface-version . "2")
|
||||
(bundled-fruix-node-cli-version . "1")
|
||||
(development-environment-helper-version
|
||||
. ,(if (null? (operating-system-development-packages os)) #f "1"))
|
||||
(build-environment-helper-version
|
||||
. ,(if (null? (operating-system-build-packages os)) #f "1"))
|
||||
(self-hosted-native-build-helper-version
|
||||
. ,(if (null? (operating-system-development-packages os)) #f "3"))
|
||||
. ,(if (null? (operating-system-build-packages os)) #f "5"))
|
||||
(user-count . ,(length (operating-system-users os)))
|
||||
(users . ,(map user-account-name (operating-system-users os)))
|
||||
(group-count . ,(length (operating-system-groups os)))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-13)
|
||||
#:use-module (rnrs io ports)
|
||||
#:export (operating-system-generated-files
|
||||
render-activation-rc-script
|
||||
render-rc-script))
|
||||
@@ -467,7 +468,57 @@
|
||||
"}\n\n"
|
||||
"load_rc_config $name\n"
|
||||
"run_rc_command \"$1\"\n")))
|
||||
(define (render-installed-system-fruix os)
|
||||
|
||||
(define (path-parent path)
|
||||
(let ((index (string-rindex path #\/)))
|
||||
(cond
|
||||
((not index) ".")
|
||||
((zero? index) "/")
|
||||
(else (substring path 0 index)))))
|
||||
|
||||
(define (read-source-file-string path)
|
||||
(call-with-input-file path get-string-all))
|
||||
|
||||
(define (bundled-fruix-node-files)
|
||||
(let* ((repo-root (or (getenv "FRUIX_PROJECT_ROOT")
|
||||
(let ((render-file (current-filename)))
|
||||
(and render-file
|
||||
(path-parent
|
||||
(path-parent
|
||||
(path-parent
|
||||
(path-parent
|
||||
(path-parent render-file)))))))
|
||||
(getcwd)))
|
||||
(guix-root (or (getenv "GUIX_SOURCE_DIR")
|
||||
(string-append (getenv "HOME") "/repos/guix")))
|
||||
(specs `((,(string-append repo-root "/scripts/fruix.scm")
|
||||
. "share/fruix/node/scripts/fruix.scm")
|
||||
(,(string-append repo-root "/modules/fruix/packages/freebsd.scm")
|
||||
. "share/fruix/node/modules/fruix/packages/freebsd.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/build.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/build.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/executor.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/executor.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/media.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/media.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/model.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/model.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/render.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/render.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/source.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/source.scm")
|
||||
(,(string-append repo-root "/modules/fruix/system/freebsd/utils.scm")
|
||||
. "share/fruix/node/modules/fruix/system/freebsd/utils.scm")
|
||||
(,(string-append guix-root "/guix/build/utils.scm")
|
||||
. "share/fruix/node/guix/guix/build/utils.scm"))))
|
||||
(map (lambda (entry)
|
||||
(cons (cdr entry)
|
||||
(read-source-file-string (car entry))))
|
||||
specs)))
|
||||
|
||||
(define (render-installed-system-fruix os guile-store guile-extra-store shepherd-store)
|
||||
(string-append
|
||||
"#!/bin/sh\n"
|
||||
"set -eu\n"
|
||||
@@ -485,6 +536,17 @@
|
||||
"rollback_generation_file=\"$system_root/rollback-generation\"\n"
|
||||
"gcroots_root=/frx/var/fruix/gcroots\n"
|
||||
"run_current_link=/run/current-system\n"
|
||||
"node_root=/run/current-system/share/fruix/node\n"
|
||||
"node_script=\"$node_root/scripts/fruix.scm\"\n"
|
||||
"node_module_root=\"$node_root/modules\"\n"
|
||||
"node_guix_root=\"$node_root/guix\"\n"
|
||||
"declaration_file=/run/current-system/metadata/system-declaration.scm\n"
|
||||
"declaration_info_file=/run/current-system/metadata/system-declaration-info.scm\n"
|
||||
"declaration_system_file=/run/current-system/metadata/system-declaration-system\n"
|
||||
"default_store_dir=/frx/store\n"
|
||||
"guile_store='" guile-store "'\n"
|
||||
"guile_extra_store='" guile-extra-store "'\n"
|
||||
"shepherd_store='" shepherd-store "'\n"
|
||||
"layout_version=2\n"
|
||||
"host_name='" (operating-system-host-name os) "'\n"
|
||||
"ready_marker='" (operating-system-ready-marker os) "'\n"
|
||||
@@ -493,6 +555,8 @@
|
||||
"{\n"
|
||||
" cat <<'EOF'\n"
|
||||
"Usage: fruix system status\n"
|
||||
" fruix system build [DECLARATION [--system NAME] ...]\n"
|
||||
" fruix system reconfigure [DECLARATION [--system NAME] ...]\n"
|
||||
" fruix system switch /frx/store/...-fruix-system-...\n"
|
||||
" fruix system rollback\n"
|
||||
"EOF\n"
|
||||
@@ -514,6 +578,10 @@
|
||||
" tr -d '\\n' < \"$1\"\n"
|
||||
" fi\n"
|
||||
"}\n\n"
|
||||
"default_system_name()\n"
|
||||
"{\n"
|
||||
" read_file_maybe \"$declaration_system_file\"\n"
|
||||
"}\n\n"
|
||||
"symlink_force()\n"
|
||||
"{\n"
|
||||
" target=$1\n"
|
||||
@@ -537,6 +605,79 @@
|
||||
" [ -f \"$closure/shepherd/init.scm\" ] || die \"closure is missing shepherd config: $closure\"\n"
|
||||
" [ -f \"$closure/boot/loader.efi\" ] || die \"closure is missing loader.efi: $closure\"\n"
|
||||
"}\n\n"
|
||||
"ensure_default_declaration()\n"
|
||||
"{\n"
|
||||
" [ -f \"$declaration_file\" ] || die \"current declaration file is missing: $declaration_file\"\n"
|
||||
" [ -f \"$declaration_info_file\" ] || die \"current declaration info file is missing: $declaration_info_file\"\n"
|
||||
" current_system_name=$(default_system_name)\n"
|
||||
" [ -n \"$current_system_name\" ] || die \"current declaration is missing a system variable name\"\n"
|
||||
"}\n\n"
|
||||
"run_node_cli()\n"
|
||||
"{\n"
|
||||
" [ -x \"$guile_store/bin/guile\" ] || die \"missing Guile runtime: $guile_store/bin/guile\"\n"
|
||||
" [ -f \"$node_script\" ] || die \"missing bundled Fruix node CLI: $node_script\"\n"
|
||||
" [ -d \"$node_module_root\" ] || die \"missing bundled Fruix modules: $node_module_root\"\n"
|
||||
" [ -d \"$node_guix_root\" ] || die \"missing bundled Guix modules: $node_guix_root\"\n"
|
||||
" guile_load_path=\"$node_module_root:$node_guix_root:$shepherd_store/share/guile/site/3.0:$guile_extra_store/share/guile/site/3.0\"\n"
|
||||
" guile_system_path=\"$guile_store/share/guile/3.0:$guile_store/share/guile/site/3.0:$guile_store/share/guile/site:$guile_store/share/guile\"\n"
|
||||
" guile_system_compiled_path=\"$guile_store/lib/guile/3.0/ccache:$guile_store/lib/guile/3.0/site-ccache\"\n"
|
||||
" guile_load_compiled_path=\"$shepherd_store/lib/guile/3.0/site-ccache:$guile_extra_store/lib/guile/3.0/site-ccache\"\n"
|
||||
" guile_system_extensions_path=\"$guile_store/lib/guile/3.0/extensions\"\n"
|
||||
" guile_extensions_path=\"$guile_extra_store/lib/guile/3.0/extensions\"\n"
|
||||
" ld_library_path=\"$guile_extra_store/lib:$guile_store/lib:/usr/local/lib\"\n"
|
||||
" env \\\n"
|
||||
" GUILE_AUTO_COMPILE=0 \\\n"
|
||||
" GUILE_SYSTEM_PATH=\"$guile_system_path\" \\\n"
|
||||
" GUILE_LOAD_PATH=\"$guile_load_path\" \\\n"
|
||||
" GUILE_SYSTEM_COMPILED_PATH=\"$guile_system_compiled_path\" \\\n"
|
||||
" GUILE_LOAD_COMPILED_PATH=\"$guile_load_compiled_path\" \\\n"
|
||||
" GUILE_SYSTEM_EXTENSIONS_PATH=\"$guile_system_extensions_path\" \\\n"
|
||||
" GUILE_EXTENSIONS_PATH=\"$guile_extensions_path\" \\\n"
|
||||
" LD_LIBRARY_PATH=\"$ld_library_path\" \\\n"
|
||||
" GUILE_PREFIX=\"$guile_store\" \\\n"
|
||||
" GUILE_EXTRA_PREFIX=\"$guile_extra_store\" \\\n"
|
||||
" SHEPHERD_PREFIX=\"$shepherd_store\" \\\n"
|
||||
" FRUIX_GUILE_STORE=\"$guile_store\" \\\n"
|
||||
" FRUIX_GUILE_EXTRA_STORE=\"$guile_extra_store\" \\\n"
|
||||
" FRUIX_SHEPHERD_STORE=\"$shepherd_store\" \\\n"
|
||||
" GUIX_SOURCE_DIR=\"$node_guix_root\" \\\n"
|
||||
" FRUIX_PROJECT_ROOT=\"$node_root\" \\\n"
|
||||
" \"$guile_store/bin/guile\" --no-auto-compile -s \"$node_script\" \"$@\"\n"
|
||||
"}\n\n"
|
||||
"system_build()\n"
|
||||
"{\n"
|
||||
" if [ $# -eq 0 ]; then\n"
|
||||
" ensure_default_declaration\n"
|
||||
" run_node_cli system build \"$declaration_file\" --system \"$current_system_name\" --store \"$default_store_dir\"\n"
|
||||
" else\n"
|
||||
" run_node_cli system build \"$@\"\n"
|
||||
" fi\n"
|
||||
"}\n\n"
|
||||
"reconfigure_system()\n"
|
||||
"{\n"
|
||||
" build_output=$(mktemp /tmp/fruix-system-reconfigure.XXXXXX)\n"
|
||||
" if [ $# -eq 0 ]; then\n"
|
||||
" ensure_default_declaration\n"
|
||||
" if ! run_node_cli system build \"$declaration_file\" --system \"$current_system_name\" --store \"$default_store_dir\" > \"$build_output\"; then\n"
|
||||
" cat \"$build_output\" >&2 || true\n"
|
||||
" rm -f \"$build_output\"\n"
|
||||
" exit 1\n"
|
||||
" fi\n"
|
||||
" else\n"
|
||||
" if ! run_node_cli system build \"$@\" > \"$build_output\"; then\n"
|
||||
" cat \"$build_output\" >&2 || true\n"
|
||||
" rm -f \"$build_output\"\n"
|
||||
" exit 1\n"
|
||||
" fi\n"
|
||||
" fi\n"
|
||||
" closure=$(sed -n 's/^closure_path=//p' \"$build_output\" | tail -n 1)\n"
|
||||
" [ -n \"$closure\" ] || die \"failed to recover closure_path from in-system build output\"\n"
|
||||
" cat \"$build_output\"\n"
|
||||
" rm -f \"$build_output\"\n"
|
||||
" switch_to_closure \"$closure\"\n"
|
||||
" printf 'reconfigure_closure=%s\\n' \"$closure\"\n"
|
||||
" printf 'reboot_required=true\\n'\n"
|
||||
"}\n\n"
|
||||
"max_generation_number()\n"
|
||||
"{\n"
|
||||
" max=0\n"
|
||||
@@ -726,6 +867,14 @@
|
||||
" [ $# -eq 2 ] || { usage >&2; exit 1; }\n"
|
||||
" status\n"
|
||||
" ;;\n"
|
||||
" build)\n"
|
||||
" shift 2\n"
|
||||
" system_build \"$@\"\n"
|
||||
" ;;\n"
|
||||
" reconfigure)\n"
|
||||
" shift 2\n"
|
||||
" reconfigure_system \"$@\"\n"
|
||||
" ;;\n"
|
||||
" switch)\n"
|
||||
" [ $# -eq 3 ] || { usage >&2; exit 1; }\n"
|
||||
" switch_to_closure \"$3\"\n"
|
||||
@@ -785,6 +934,33 @@
|
||||
"export MAKEFLAGS=\"-m $profile/usr/share/mk\"\n"
|
||||
"export PATH=\"/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$profile/bin:$profile/sbin:$profile/usr/bin:$profile/usr/sbin\"\n"
|
||||
"EOF\n"))
|
||||
(define (render-build-environment-script os)
|
||||
(string-append
|
||||
"#!/bin/sh\n"
|
||||
"set -eu\n"
|
||||
"profile=/run/current-system/build-profile\n"
|
||||
"[ -d \"$profile\" ] || {\n"
|
||||
" echo \"fruix-build-environment: build profile is not available\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"cat <<EOF\n"
|
||||
"unset MAKEOBJDIRPREFIX MAKEFLAGS CC CXX AR RANLIB NM CPPFLAGS CFLAGS CXXFLAGS LDFLAGS\n"
|
||||
"unset FRUIX_DEVELOPMENT_PROFILE FRUIX_DEVELOPMENT_INCLUDE FRUIX_DEVELOPMENT_LIB FRUIX_DEVELOPMENT_SHARE_MK\n"
|
||||
"unset FRUIX_DEVELOPMENT_BIN FRUIX_DEVELOPMENT_USR_BIN FRUIX_CC FRUIX_CXX FRUIX_AR FRUIX_RANLIB FRUIX_NM FRUIX_BMAKE\n"
|
||||
"export FRUIX_BUILD_PROFILE=\"$profile\"\n"
|
||||
"export FRUIX_BUILD_INCLUDE=\"$profile/usr/include\"\n"
|
||||
"export FRUIX_BUILD_LIB=\"$profile/lib\"\n"
|
||||
"export FRUIX_BUILD_SHARE_MK=\"$profile/usr/share/mk\"\n"
|
||||
"export FRUIX_BUILD_BIN=\"$profile/bin\"\n"
|
||||
"export FRUIX_BUILD_USR_BIN=\"$profile/usr/bin\"\n"
|
||||
"export FRUIX_BUILD_CC=\"$profile/bin/cc\"\n"
|
||||
"export FRUIX_BUILD_CXX=\"$profile/bin/c++\"\n"
|
||||
"export FRUIX_BUILD_AR=\"$profile/bin/ar\"\n"
|
||||
"export FRUIX_BUILD_RANLIB=\"$profile/bin/ranlib\"\n"
|
||||
"export FRUIX_BUILD_NM=\"$profile/bin/nm\"\n"
|
||||
"export FRUIX_BMAKE=\"make\"\n"
|
||||
"export PATH=\"/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$profile/bin:$profile/sbin:$profile/usr/bin:$profile/usr/sbin\"\n"
|
||||
"EOF\n"))
|
||||
(define (render-self-hosted-native-build-script os)
|
||||
(let* ((base-spec (freebsd-base-spec (operating-system-freebsd-base os)))
|
||||
(base-name (assoc-ref base-spec 'name))
|
||||
@@ -807,25 +983,26 @@
|
||||
"#!/bin/sh\n"
|
||||
"set -eu\n"
|
||||
"umask 022\n"
|
||||
"profile=/run/current-system/development-profile\n"
|
||||
"profile=/run/current-system/build-profile\n"
|
||||
"guest_host_name='" (operating-system-host-name os) "'\n"
|
||||
"[ -d \"$profile\" ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: development profile is not available\" >&2\n"
|
||||
" echo \"fruix-self-hosted-native-build: build profile is not available\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"[ -x /usr/local/bin/fruix-development-environment ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: development environment helper is missing\" >&2\n"
|
||||
"[ -x /usr/local/bin/fruix-build-environment ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: build environment helper is missing\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"eval \"$(/usr/local/bin/fruix-build-environment)\"\n"
|
||||
"[ \"${FRUIX_BUILD_PROFILE:-}\" = \"$profile\" ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: build environment helper exported an unexpected profile\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin\n"
|
||||
"unset MAKEOBJDIRPREFIX MAKEFLAGS CC CXX AR RANLIB NM CPPFLAGS CFLAGS CXXFLAGS LDFLAGS\n"
|
||||
"unset FRUIX_DEVELOPMENT_PROFILE FRUIX_DEVELOPMENT_INCLUDE FRUIX_DEVELOPMENT_LIB FRUIX_DEVELOPMENT_SHARE_MK\n"
|
||||
"unset FRUIX_DEVELOPMENT_BIN FRUIX_DEVELOPMENT_USR_BIN FRUIX_CC FRUIX_CXX FRUIX_AR FRUIX_RANLIB FRUIX_NM FRUIX_BMAKE\n"
|
||||
"[ -L /usr/include ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: /usr/include compatibility link is missing\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"[ \"$(readlink /usr/include)\" = \"/run/current-system/development-profile/usr/include\" ] || {\n"
|
||||
"[ \"$(readlink /usr/include)\" = \"/run/current-system/build-profile/usr/include\" ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: /usr/include points at the wrong target\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
@@ -833,10 +1010,11 @@
|
||||
" echo \"fruix-self-hosted-native-build: /usr/share/mk compatibility link is missing\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"[ \"$(readlink /usr/share/mk)\" = \"/run/current-system/development-profile/usr/share/mk\" ] || {\n"
|
||||
"[ \"$(readlink /usr/share/mk)\" = \"/run/current-system/build-profile/usr/share/mk\" ] || {\n"
|
||||
" echo \"fruix-self-hosted-native-build: /usr/share/mk points at the wrong target\" >&2\n"
|
||||
" exit 1\n"
|
||||
"}\n"
|
||||
"make_cmd=${FRUIX_BMAKE:-make}\n"
|
||||
"jobs=${FRUIX_SELF_HOSTED_NATIVE_BUILD_JOBS:-$(sysctl -n hw.ncpu)}\n"
|
||||
"case \"$jobs\" in\n"
|
||||
" ''|*[!0-9]*)\n"
|
||||
@@ -887,11 +1065,11 @@
|
||||
"}\n"
|
||||
"mkdir -p \"$world_artifact\" \"$headers_artifact/usr\" \"$kernel_artifact/boot\" \"$bootloader_artifact/boot\"\n"
|
||||
"export MAKEOBJDIRPREFIX=\"$build_root/obj\"\n"
|
||||
"make -j\"$jobs\" -C \"$source_root\" " build-common " buildworld > \"$logdir/buildworld.log\" 2>&1\n"
|
||||
"make -j\"$jobs\" -C \"$source_root\" " build-common " buildkernel > \"$logdir/buildkernel.log\" 2>&1\n"
|
||||
"make -C \"$source_root\" " install-common " DESTDIR=\"$world_stage\" installworld > \"$logdir/installworld.log\" 2>&1\n"
|
||||
"make -C \"$source_root\" " install-common " DESTDIR=\"$world_stage\" distribution > \"$logdir/distribution.log\" 2>&1\n"
|
||||
"make -C \"$source_root\" " install-common " DESTDIR=\"$kernel_stage\" installkernel > \"$logdir/installkernel.log\" 2>&1\n"
|
||||
"\"$make_cmd\" -j\"$jobs\" -C \"$source_root\" " build-common " buildworld > \"$logdir/buildworld.log\" 2>&1\n"
|
||||
"\"$make_cmd\" -j\"$jobs\" -C \"$source_root\" " build-common " buildkernel > \"$logdir/buildkernel.log\" 2>&1\n"
|
||||
"\"$make_cmd\" -C \"$source_root\" " install-common " DESTDIR=\"$world_stage\" installworld > \"$logdir/installworld.log\" 2>&1\n"
|
||||
"\"$make_cmd\" -C \"$source_root\" " install-common " DESTDIR=\"$world_stage\" distribution > \"$logdir/distribution.log\" 2>&1\n"
|
||||
"\"$make_cmd\" -C \"$source_root\" " install-common " DESTDIR=\"$kernel_stage\" installkernel > \"$logdir/installkernel.log\" 2>&1\n"
|
||||
"cp -a \"$world_stage/.\" \"$world_artifact/\"\n"
|
||||
"cp -a \"$kernel_stage/boot/kernel\" \"$kernel_artifact/boot/kernel\"\n"
|
||||
"cp -a \"$world_stage/usr/include\" \"$headers_artifact/usr/include\"\n"
|
||||
@@ -928,12 +1106,17 @@
|
||||
"ln -s \"$result_root\" \"$latest_link\"\n"
|
||||
"cat >\"$promotion_file\" <<EOF\n"
|
||||
"((native-build-result-version . \"1\")\n"
|
||||
" (executor . \"guest-self-hosted\")\n"
|
||||
" (executor-version . \"3\")\n"
|
||||
" (executor . ((kind . self-hosted)\n"
|
||||
" (name . \"guest-self-hosted\")\n"
|
||||
" (version . \"5\")\n"
|
||||
" (properties . ((helper-path . \"/usr/local/bin/fruix-self-hosted-native-build\")\n"
|
||||
" (guest-host-name . \"$guest_host_name\")\n"
|
||||
" (build-root-base . \"$build_root_base\")\n"
|
||||
" (result-root-base . \"$result_root_base\")))))\n"
|
||||
" (run-id . \"$run_id\")\n"
|
||||
" (guest-host-name . \"$guest_host_name\")\n"
|
||||
" (closure-path . \"$closure\")\n"
|
||||
" (development-profile . \"$profile\")\n"
|
||||
" (build-profile . \"$profile\")\n"
|
||||
" (freebsd-base . ((name . \"" base-name "\")\n"
|
||||
" (version-label . \"" version-label "\")\n"
|
||||
" (release . \"" release "\")\n"
|
||||
@@ -961,10 +1144,13 @@
|
||||
"EOF\n"
|
||||
"cat >\"$metadata_file\" <<EOF\n"
|
||||
"run_id=$run_id\n"
|
||||
"helper_version=3\n"
|
||||
"helper_version=5\n"
|
||||
"executor_kind=self-hosted\n"
|
||||
"executor_name=guest-self-hosted\n"
|
||||
"executor_version=5\n"
|
||||
"closure_path=$closure\n"
|
||||
"guest_host_name=$guest_host_name\n"
|
||||
"development_profile=$profile\n"
|
||||
"build_profile=$profile\n"
|
||||
"source_store=$source_store\n"
|
||||
"source_root=$source_root\n"
|
||||
"build_jobs=$jobs\n"
|
||||
@@ -1022,11 +1208,17 @@
|
||||
#:guile-extra-store guile-extra-store
|
||||
#:shepherd-store shepherd-store))
|
||||
("shepherd/init.scm" . ,(render-shepherd-config os))
|
||||
("usr/local/bin/fruix" . ,(render-installed-system-fruix os)))
|
||||
("usr/local/bin/fruix"
|
||||
. ,(render-installed-system-fruix os guile-store guile-extra-store shepherd-store)))
|
||||
(bundled-fruix-node-files)
|
||||
(if (null? (operating-system-development-packages os))
|
||||
'()
|
||||
`(("usr/local/bin/fruix-development-environment"
|
||||
. ,(render-development-environment-script os))
|
||||
. ,(render-development-environment-script os))))
|
||||
(if (null? (operating-system-build-packages os))
|
||||
'()
|
||||
`(("usr/local/bin/fruix-build-environment"
|
||||
. ,(render-build-environment-script os))
|
||||
("usr/local/bin/fruix-self-hosted-native-build"
|
||||
. ,(render-self-hosted-native-build-script os))))
|
||||
(if (pid1-init-mode? os)
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
(ice-9 format)
|
||||
(ice-9 match)
|
||||
(srfi srfi-1)
|
||||
(srfi srfi-13))
|
||||
(srfi srfi-13)
|
||||
(rnrs io ports))
|
||||
|
||||
(define (usage code)
|
||||
(format (if (= code 0) #t (current-error-port))
|
||||
@@ -69,6 +70,9 @@ Common options:\n\
|
||||
(format #t "~a=~a~%" (car field) (stringify (cdr field))))
|
||||
fields))
|
||||
|
||||
(define (read-file-string file)
|
||||
(call-with-input-file file get-string-all))
|
||||
|
||||
(define (lookup-bound-value module symbol)
|
||||
(let ((var (module-variable module symbol)))
|
||||
(and var (variable-ref var))))
|
||||
@@ -580,6 +584,9 @@ Common options:\n\
|
||||
`((action . "promote")
|
||||
(result_root . ,result-root)
|
||||
(store_dir . ,store-dir)
|
||||
(executor_kind . ,(assoc-ref result 'executor-kind))
|
||||
(executor_name . ,(assoc-ref result 'executor-name))
|
||||
(executor_version . ,(assoc-ref result 'executor-version))
|
||||
(result_store . ,(assoc-ref result 'result-store))
|
||||
(result_metadata_file . ,(assoc-ref result 'result-metadata-file))
|
||||
(artifact_store_count . ,(assoc-ref result 'artifact-store-count))
|
||||
@@ -626,7 +633,11 @@ Common options:\n\
|
||||
(lambda (os resolved-symbol)
|
||||
(let* ((guile-prefix (or (getenv "GUILE_PREFIX") "/tmp/guile-freebsd-validate-install"))
|
||||
(guile-extra-prefix (or (getenv "GUILE_EXTRA_PREFIX") "/tmp/guile-gnutls-freebsd-validate-install"))
|
||||
(shepherd-prefix (or (getenv "SHEPHERD_PREFIX") "/tmp/shepherd-freebsd-validate-install")))
|
||||
(shepherd-prefix (or (getenv "SHEPHERD_PREFIX") "/tmp/shepherd-freebsd-validate-install"))
|
||||
(guile-store-path (getenv "FRUIX_GUILE_STORE"))
|
||||
(guile-extra-store-path (getenv "FRUIX_GUILE_EXTRA_STORE"))
|
||||
(shepherd-store-path (getenv "FRUIX_SHEPHERD_STORE"))
|
||||
(declaration-source (read-file-string os-file)))
|
||||
(cond
|
||||
((string=? action "build")
|
||||
(emit-system-build-metadata
|
||||
@@ -635,7 +646,13 @@ Common options:\n\
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix)))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:guile-store-path guile-store-path
|
||||
#:guile-extra-store-path guile-extra-store-path
|
||||
#:shepherd-store-path shepherd-store-path
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin os-file
|
||||
#:declaration-system-symbol resolved-symbol)))
|
||||
((string=? action "rootfs")
|
||||
(unless rootfs
|
||||
(error "rootfs action requires ROOTFS-DIR or --rootfs DIR"))
|
||||
@@ -643,7 +660,10 @@ Common options:\n\
|
||||
#:store-dir store-dir
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix)))
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin os-file
|
||||
#:declaration-system-symbol resolved-symbol)))
|
||||
(emit-metadata
|
||||
`((action . "rootfs")
|
||||
(os_file . ,os-file)
|
||||
@@ -661,6 +681,9 @@ Common options:\n\
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin os-file
|
||||
#:declaration-system-symbol resolved-symbol
|
||||
#:root-size (or root-size "256m")
|
||||
#:disk-capacity disk-capacity)))
|
||||
((string=? action "installer")
|
||||
@@ -671,6 +694,9 @@ Common options:\n\
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin os-file
|
||||
#:declaration-system-symbol resolved-symbol
|
||||
#:install-target-device (or install-target-device "/dev/vtbd1")
|
||||
#:root-size (or root-size "10g")
|
||||
#:disk-capacity disk-capacity)))
|
||||
@@ -682,6 +708,9 @@ Common options:\n\
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin os-file
|
||||
#:declaration-system-symbol resolved-symbol
|
||||
#:install-target-device (or install-target-device "/dev/vtbd0")
|
||||
#:root-size root-size)))
|
||||
((string=? action "install")
|
||||
@@ -695,6 +724,9 @@ Common options:\n\
|
||||
#:guile-prefix guile-prefix
|
||||
#:guile-extra-prefix guile-extra-prefix
|
||||
#:shepherd-prefix shepherd-prefix
|
||||
#:declaration-source declaration-source
|
||||
#:declaration-origin os-file
|
||||
#:declaration-system-symbol resolved-symbol
|
||||
#:root-size root-size
|
||||
#:disk-capacity disk-capacity))))))))))
|
||||
((string=? command "source")
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#:base-packages %freebsd-native-system-packages
|
||||
#:development-packages (list freebsd-native-headers
|
||||
freebsd-clang-toolchain)
|
||||
#:build-packages (list freebsd-native-headers
|
||||
freebsd-clang-toolchain)
|
||||
#:groups (list (user-group #:name "wheel" #:gid 0 #:system? #t)
|
||||
(user-group #:name "sshd" #:gid 22 #:system? #t)
|
||||
(user-group #:name "_dhcp" #:gid 65 #:system? #t)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
(use-modules (fruix system freebsd)
|
||||
(fruix packages freebsd))
|
||||
|
||||
(define phase20-promoted-native-build-result
|
||||
(promoted-native-build-result
|
||||
#:store-path "__PROMOTED_RESULT_STORE__"))
|
||||
|
||||
(define phase20-promoted-native-base-operating-system
|
||||
(operating-system-from-promoted-native-build-result
|
||||
phase20-promoted-native-build-result
|
||||
#:host-name "fruix-freebsd"
|
||||
#:groups (list (user-group #:name "wheel" #:gid 0 #:system? #t)
|
||||
(user-group #:name "sshd" #:gid 22 #:system? #t)
|
||||
(user-group #:name "_dhcp" #:gid 65 #:system? #t)
|
||||
(user-group #:name "operator" #:gid 1000 #:system? #f))
|
||||
#:users (list (user-account #:name "root"
|
||||
#:uid 0
|
||||
#:group "wheel"
|
||||
#:comment "Charlie &"
|
||||
#:home "/root"
|
||||
#:shell "/bin/sh"
|
||||
#:system? #t)
|
||||
(user-account #:name "sshd"
|
||||
#:uid 22
|
||||
#:group "sshd"
|
||||
#:comment "Secure Shell Daemon"
|
||||
#:home "/var/empty"
|
||||
#:shell "/usr/sbin/nologin"
|
||||
#:system? #t)
|
||||
(user-account #:name "_dhcp"
|
||||
#:uid 65
|
||||
#:group "_dhcp"
|
||||
#:comment "dhcp programs"
|
||||
#:home "/var/empty"
|
||||
#:shell "/usr/sbin/nologin"
|
||||
#:system? #t)
|
||||
(user-account #:name "operator"
|
||||
#:uid 1000
|
||||
#:group "operator"
|
||||
#:supplementary-groups '("wheel")
|
||||
#:comment "Fruix Operator"
|
||||
#:home "/home/operator"
|
||||
#:shell "/bin/sh"
|
||||
#:system? #f))
|
||||
#:file-systems (list (file-system #:device "/dev/gpt/fruix-root"
|
||||
#:mount-point "/"
|
||||
#:type "ufs"
|
||||
#:options "rw"
|
||||
#:needed-for-boot? #t)
|
||||
(file-system #:device "devfs"
|
||||
#:mount-point "/dev"
|
||||
#:type "devfs"
|
||||
#:options "rw"
|
||||
#:needed-for-boot? #t)
|
||||
(file-system #:device "tmpfs"
|
||||
#:mount-point "/tmp"
|
||||
#:type "tmpfs"
|
||||
#:options "rw,size=64m"))
|
||||
#:services '(shepherd ready-marker sshd)
|
||||
#:loader-entries '(("autoboot_delay" . "1")
|
||||
("boot_multicons" . "YES")
|
||||
("boot_serial" . "YES")
|
||||
("console" . "comconsole,vidconsole"))
|
||||
#:rc-conf-entries '(("clear_tmp_enable" . "NO")
|
||||
("hostid_enable" . "NO")
|
||||
("sendmail_enable" . "NONE")
|
||||
("sshd_enable" . "YES")
|
||||
("ifconfig_xn0" . "SYNCDHCP")
|
||||
("ifconfig_em0" . "SYNCDHCP")
|
||||
("ifconfig_vtnet0" . "SYNCDHCP"))
|
||||
#:init-mode 'shepherd-pid1
|
||||
#:ready-marker "/var/lib/fruix/ready"
|
||||
#:root-authorized-keys '("__ROOT_AUTHORIZED_KEY__")))
|
||||
@@ -0,0 +1,73 @@
|
||||
(use-modules (fruix system freebsd)
|
||||
(fruix packages freebsd))
|
||||
|
||||
(define postphase20-promoted-native-build-result
|
||||
(promoted-native-build-result
|
||||
#:store-path "__PROMOTED_RESULT_STORE__"))
|
||||
|
||||
(define postphase20-installed-node-operating-system
|
||||
(operating-system-from-promoted-native-build-result
|
||||
postphase20-promoted-native-build-result
|
||||
#:host-name "__HOST_NAME__"
|
||||
#:groups (list (user-group #:name "wheel" #:gid 0 #:system? #t)
|
||||
(user-group #:name "sshd" #:gid 22 #:system? #t)
|
||||
(user-group #:name "_dhcp" #:gid 65 #:system? #t)
|
||||
(user-group #:name "operator" #:gid 1000 #:system? #f))
|
||||
#:users (list (user-account #:name "root"
|
||||
#:uid 0
|
||||
#:group "wheel"
|
||||
#:comment "Charlie &"
|
||||
#:home "/root"
|
||||
#:shell "/bin/sh"
|
||||
#:system? #t)
|
||||
(user-account #:name "sshd"
|
||||
#:uid 22
|
||||
#:group "sshd"
|
||||
#:comment "Secure Shell Daemon"
|
||||
#:home "/var/empty"
|
||||
#:shell "/usr/sbin/nologin"
|
||||
#:system? #t)
|
||||
(user-account #:name "_dhcp"
|
||||
#:uid 65
|
||||
#:group "_dhcp"
|
||||
#:comment "dhcp programs"
|
||||
#:home "/var/empty"
|
||||
#:shell "/usr/sbin/nologin"
|
||||
#:system? #t)
|
||||
(user-account #:name "operator"
|
||||
#:uid 1000
|
||||
#:group "operator"
|
||||
#:supplementary-groups '("wheel")
|
||||
#:comment "Fruix Operator"
|
||||
#:home "/home/operator"
|
||||
#:shell "/bin/sh"
|
||||
#:system? #f))
|
||||
#:file-systems (list (file-system #:device "/dev/gpt/fruix-root"
|
||||
#:mount-point "/"
|
||||
#:type "ufs"
|
||||
#:options "rw"
|
||||
#:needed-for-boot? #t)
|
||||
(file-system #:device "devfs"
|
||||
#:mount-point "/dev"
|
||||
#:type "devfs"
|
||||
#:options "rw"
|
||||
#:needed-for-boot? #t)
|
||||
(file-system #:device "tmpfs"
|
||||
#:mount-point "/tmp"
|
||||
#:type "tmpfs"
|
||||
#:options "rw,size=64m"))
|
||||
#:services '(shepherd ready-marker sshd)
|
||||
#:loader-entries '(("autoboot_delay" . "1")
|
||||
("boot_multicons" . "YES")
|
||||
("boot_serial" . "YES")
|
||||
("console" . "comconsole,vidconsole"))
|
||||
#:rc-conf-entries '(("clear_tmp_enable" . "NO")
|
||||
("hostid_enable" . "NO")
|
||||
("sendmail_enable" . "NONE")
|
||||
("sshd_enable" . "YES")
|
||||
("ifconfig_xn0" . "SYNCDHCP")
|
||||
("ifconfig_em0" . "SYNCDHCP")
|
||||
("ifconfig_vtnet0" . "SYNCDHCP"))
|
||||
#:init-mode 'shepherd-pid1
|
||||
#:ready-marker "/var/lib/fruix/ready"
|
||||
#:root-authorized-keys '("__ROOT_AUTHORIZED_KEY__")))
|
||||
@@ -50,8 +50,10 @@ guile_module_smoke=$(sed -n 's/^guile_module_smoke=//p' "$inner_metadata")
|
||||
activate_log=$(sed -n 's/^activate_log=//p' "$inner_metadata")
|
||||
|
||||
development_profile_path=$closure_path/development-profile
|
||||
build_profile_path=$closure_path/build-profile
|
||||
runtime_profile_path=$closure_path/profile
|
||||
development_env_script=$closure_path/usr/local/bin/fruix-development-environment
|
||||
build_env_script=$closure_path/usr/local/bin/fruix-build-environment
|
||||
|
||||
[ "$shepherd_pid" = 1 ] || { echo "shepherd was not PID 1" >&2; exit 1; }
|
||||
[ "$sshd_status" = running ] || { echo "sshd is not running" >&2; exit 1; }
|
||||
@@ -68,7 +70,11 @@ for path in \
|
||||
"$development_profile_path/bin/ar" \
|
||||
"$development_profile_path/usr/include/sys/param.h" \
|
||||
"$development_profile_path/usr/share/mk/bsd.prog.mk" \
|
||||
"$development_env_script"
|
||||
"$build_profile_path/bin/cc" \
|
||||
"$build_profile_path/usr/include/sys/param.h" \
|
||||
"$build_profile_path/usr/share/mk/bsd.prog.mk" \
|
||||
"$development_env_script" \
|
||||
"$build_env_script"
|
||||
do
|
||||
[ -e "$path" ] || {
|
||||
echo "required development environment path missing: $path" >&2
|
||||
@@ -96,8 +102,11 @@ guest_dev_metadata=$(ssh -i "$root_ssh_private_key_file" \
|
||||
root@"$guest_ip" 'sh -s' <<'EOF'
|
||||
set -eu
|
||||
[ -x /usr/local/bin/fruix-development-environment ]
|
||||
[ -x /usr/local/bin/fruix-build-environment ]
|
||||
[ -L /run/current-development ]
|
||||
[ "$(readlink /run/current-development)" = "/run/current-system/development-profile" ]
|
||||
[ -L /run/current-build ]
|
||||
[ "$(readlink /run/current-build)" = "/run/current-system/build-profile" ]
|
||||
exports=$(/usr/local/bin/fruix-development-environment)
|
||||
printf '%s\n' "$exports" | grep '^export FRUIX_DEVELOPMENT_PROFILE="/run/current-system/development-profile"$' >/dev/null
|
||||
printf '%s\n' "$exports" | grep '^export MAKEFLAGS="-m /run/current-system/development-profile/usr/share/mk"$' >/dev/null
|
||||
@@ -109,6 +118,20 @@ eval "$exports"
|
||||
[ -f "$FRUIX_DEVELOPMENT_INCLUDE/sys/param.h" ]
|
||||
[ -f "$FRUIX_DEVELOPMENT_SHARE_MK/bsd.prog.mk" ]
|
||||
cc_version=$($FRUIX_CC --version | awk 'NR==1 { print; exit }')
|
||||
build_exports=$(/usr/local/bin/fruix-build-environment)
|
||||
printf '%s\n' "$build_exports" | grep '^unset MAKEOBJDIRPREFIX MAKEFLAGS CC CXX AR RANLIB NM CPPFLAGS CFLAGS CXXFLAGS LDFLAGS$' >/dev/null
|
||||
printf '%s\n' "$build_exports" | grep '^export FRUIX_BUILD_PROFILE="/run/current-system/build-profile"$' >/dev/null
|
||||
eval "$build_exports"
|
||||
[ -d "$FRUIX_BUILD_PROFILE" ]
|
||||
[ -f "$FRUIX_BUILD_INCLUDE/sys/param.h" ]
|
||||
[ -f "$FRUIX_BUILD_SHARE_MK/bsd.prog.mk" ]
|
||||
[ "${MAKEFLAGS-unset}" = unset ]
|
||||
[ "${CPPFLAGS-unset}" = unset ]
|
||||
[ "${CFLAGS-unset}" = unset ]
|
||||
[ "${LDFLAGS-unset}" = unset ]
|
||||
[ "$FRUIX_BMAKE" = make ]
|
||||
build_profile_value=$FRUIX_BUILD_PROFILE
|
||||
eval "$exports"
|
||||
tmp=/tmp/fruix-phase20-development-env
|
||||
rm -rf "$tmp"
|
||||
mkdir -p "$tmp/direct" "$tmp/mk"
|
||||
@@ -142,25 +165,34 @@ hello_make=$(./hello)
|
||||
make_log_tail=$(tail -n 20 "$tmp/mk/make.log" | tr '\n' ' ')
|
||||
exports_flat=$(printf '%s' "$exports" | tr '\n' ' ')
|
||||
printf 'development_profile=%s\n' "$FRUIX_DEVELOPMENT_PROFILE"
|
||||
printf 'build_profile=%s\n' "$build_profile_value"
|
||||
printf 'cc_version=%s\n' "$cc_version"
|
||||
printf 'hello_direct=%s\n' "$hello_direct"
|
||||
printf 'hello_make=%s\n' "$hello_make"
|
||||
build_exports_flat=$(printf '%s' "$build_exports" | tr '\n' ' ')
|
||||
printf 'exports=%s\n' "$exports_flat"
|
||||
printf 'build_exports=%s\n' "$build_exports_flat"
|
||||
printf 'make_log_tail=%s\n' "$make_log_tail"
|
||||
EOF
|
||||
)
|
||||
|
||||
development_profile=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^development_profile=//p')
|
||||
build_profile=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^build_profile=//p')
|
||||
cc_version=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^cc_version=//p')
|
||||
hello_direct=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^hello_direct=//p')
|
||||
hello_make=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^hello_make=//p')
|
||||
development_exports=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^exports=//p')
|
||||
build_exports=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^build_exports=//p')
|
||||
make_log_tail=$(printf '%s\n' "$guest_dev_metadata" | sed -n 's/^make_log_tail=//p')
|
||||
|
||||
[ "$development_profile" = "/run/current-system/development-profile" ] || {
|
||||
echo "unexpected guest development profile path: $development_profile" >&2
|
||||
exit 1
|
||||
}
|
||||
[ "$build_profile" = "/run/current-system/build-profile" ] || {
|
||||
echo "unexpected guest build profile path: $build_profile" >&2
|
||||
exit 1
|
||||
}
|
||||
case "$cc_version" in
|
||||
*"FreeBSD clang version"*) : ;;
|
||||
*) echo "unexpected cc version output: $cc_version" >&2; exit 1 ;;
|
||||
@@ -177,6 +209,10 @@ case "$development_exports" in
|
||||
*'export FRUIX_CC="/run/current-system/development-profile/bin/cc"'*) : ;;
|
||||
*) echo "development environment exports do not include FRUIX_CC" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$build_exports" in
|
||||
*'export FRUIX_BUILD_PROFILE="/run/current-system/build-profile"'*) : ;;
|
||||
*) echo "build environment exports do not include FRUIX_BUILD_PROFILE" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
cat >"$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
@@ -189,16 +225,20 @@ vdi_id=$vdi_id
|
||||
guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
development_profile_path=$development_profile_path
|
||||
build_profile_path=$build_profile_path
|
||||
development_env_script=$development_env_script
|
||||
build_env_script=$build_env_script
|
||||
shepherd_pid=$shepherd_pid
|
||||
sshd_status=$sshd_status
|
||||
compat_prefix_shims=$compat_prefix_shims
|
||||
guile_module_smoke=$guile_module_smoke
|
||||
development_profile_guest=$development_profile
|
||||
build_profile_guest=$build_profile
|
||||
cc_version=$cc_version
|
||||
hello_direct=$hello_direct
|
||||
hello_make=$hello_make
|
||||
development_exports=$development_exports
|
||||
build_exports=$build_exports
|
||||
make_log_tail=$make_log_tail
|
||||
boot_backend=xcp-ng-xo-cli
|
||||
init_mode=shepherd-pid1
|
||||
|
||||
239
tests/system/run-phase20-host-initiated-native-build-store-promotion-xcpng.sh
Executable file
239
tests/system/run-phase20-host-initiated-native-build-store-promotion-xcpng.sh
Executable file
@@ -0,0 +1,239 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo_root=${PROJECT_ROOT:-$(pwd)}
|
||||
os_template=${OS_TEMPLATE:-$repo_root/tests/system/phase20-development-operating-system.scm.in}
|
||||
system_name=${SYSTEM_NAME:-phase20-operating-system}
|
||||
root_size=${ROOT_SIZE:-20g}
|
||||
store_dir=${STORE_DIR:-/frx/store}
|
||||
metadata_target=${METADATA_OUT:-}
|
||||
root_authorized_key_file=${ROOT_AUTHORIZED_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}
|
||||
root_ssh_private_key_file=${ROOT_SSH_PRIVATE_KEY_FILE:-$HOME/.ssh/id_ed25519}
|
||||
cleanup=0
|
||||
|
||||
if [ -n "${WORKDIR:-}" ]; then
|
||||
workdir=$WORKDIR
|
||||
mkdir -p "$workdir"
|
||||
else
|
||||
workdir=$(mktemp -d /tmp/fruix-phase20-host-initiated-native-build-store-promotion-xcpng.XXXXXX)
|
||||
cleanup=1
|
||||
fi
|
||||
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
||||
cleanup=0
|
||||
fi
|
||||
|
||||
inner_metadata=$workdir/phase20-host-initiated-native-build-store-promotion-inner-metadata.txt
|
||||
promotion_out=$workdir/native-build-promote.txt
|
||||
metadata_file=$workdir/phase20-host-initiated-native-build-store-promotion-xcpng-metadata.txt
|
||||
import_root=$workdir/import
|
||||
|
||||
action_cleanup() {
|
||||
if [ "$cleanup" -eq 1 ]; then
|
||||
rm -rf "$workdir"
|
||||
fi
|
||||
}
|
||||
trap action_cleanup EXIT INT TERM
|
||||
|
||||
KEEP_WORKDIR=1 WORKDIR="$workdir/inner" METADATA_OUT="$inner_metadata" \
|
||||
ROOT_AUTHORIZED_KEY_FILE="$root_authorized_key_file" \
|
||||
ROOT_SSH_PRIVATE_KEY_FILE="$root_ssh_private_key_file" \
|
||||
OS_TEMPLATE="$os_template" SYSTEM_NAME="$system_name" ROOT_SIZE="$root_size" \
|
||||
"$repo_root/tests/system/run-phase20-host-initiated-native-build-xcpng.sh"
|
||||
|
||||
guest_ip=$(sed -n 's/^guest_ip=//p' "$inner_metadata")
|
||||
vm_id=$(sed -n 's/^vm_id=//p' "$inner_metadata")
|
||||
vdi_id=$(sed -n 's/^vdi_id=//p' "$inner_metadata")
|
||||
closure_path=$(sed -n 's/^closure_path=//p' "$inner_metadata")
|
||||
closure_base=$(sed -n 's/^closure_base=//p' "$inner_metadata")
|
||||
run_id=$(sed -n 's/^run_id=//p' "$inner_metadata")
|
||||
source_store=$(sed -n 's/^source_store=//p' "$inner_metadata")
|
||||
result_root=$(sed -n 's/^result_root=//p' "$inner_metadata")
|
||||
promotion_file=$(sed -n 's/^promotion_file=//p' "$inner_metadata")
|
||||
world_artifact=$(sed -n 's/^world_artifact=//p' "$inner_metadata")
|
||||
kernel_artifact=$(sed -n 's/^kernel_artifact=//p' "$inner_metadata")
|
||||
headers_artifact=$(sed -n 's/^headers_artifact=//p' "$inner_metadata")
|
||||
bootloader_artifact=$(sed -n 's/^bootloader_artifact=//p' "$inner_metadata")
|
||||
sha_kernel=$(sed -n 's/^sha_kernel=//p' "$inner_metadata")
|
||||
sha_loader=$(sed -n 's/^sha_loader=//p' "$inner_metadata")
|
||||
sha_param=$(sed -n 's/^sha_param=//p' "$inner_metadata")
|
||||
|
||||
ssh_guest() {
|
||||
ssh -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
root@"$guest_ip" "$@"
|
||||
}
|
||||
|
||||
mkdir -p "$import_root"
|
||||
result_base=$(basename "$result_root")
|
||||
ssh -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
root@"$guest_ip" "tar -C '$(dirname "$result_root")' -cf - '$result_base'" | tar -C "$import_root" -xf -
|
||||
local_result_root=$import_root/$result_base
|
||||
[ -d "$local_result_root" ] || { echo "failed to import native build result root" >&2; exit 1; }
|
||||
[ -f "$local_result_root/promotion.scm" ] || { echo "imported result is missing promotion.scm" >&2; exit 1; }
|
||||
[ -f "$local_result_root/artifacts/world/bin/sh" ] || { echo "imported result is missing world artifact" >&2; exit 1; }
|
||||
[ -f "$local_result_root/artifacts/kernel/boot/kernel/kernel" ] || { echo "imported result is missing kernel artifact" >&2; exit 1; }
|
||||
[ -f "$local_result_root/artifacts/headers/usr/include/sys/param.h" ] || { echo "imported result is missing headers artifact" >&2; exit 1; }
|
||||
[ -f "$local_result_root/artifacts/bootloader/boot/loader.efi" ] || { echo "imported result is missing bootloader artifact" >&2; exit 1; }
|
||||
|
||||
action_env() {
|
||||
sudo env \
|
||||
HOME="$HOME" \
|
||||
GUILE_AUTO_COMPILE=0 \
|
||||
GUIX_SOURCE_DIR="${GUIX_SOURCE_DIR:-$HOME/repos/guix}" \
|
||||
GUILE_BIN="${GUILE_BIN:-/tmp/guile-freebsd-validate-install/bin/guile}" \
|
||||
GUILE_EXTRA_PREFIX="${GUILE_EXTRA_PREFIX:-/tmp/guile-gnutls-freebsd-validate-install}" \
|
||||
SHEPHERD_PREFIX="${SHEPHERD_PREFIX:-/tmp/shepherd-freebsd-validate-install}" \
|
||||
"$@"
|
||||
}
|
||||
|
||||
action_env "$repo_root/bin/fruix" native-build promote "$local_result_root" --store "$store_dir" >"$promotion_out"
|
||||
|
||||
field() {
|
||||
sed -n "s/^$1=//p" "$promotion_out" | tail -n 1
|
||||
}
|
||||
|
||||
executor_kind=$(field executor_kind)
|
||||
executor_name=$(field executor_name)
|
||||
executor_version=$(field executor_version)
|
||||
result_store=$(field result_store)
|
||||
result_metadata_file=$(field result_metadata_file)
|
||||
artifact_store_count=$(field artifact_store_count)
|
||||
artifact_stores=$(field artifact_stores)
|
||||
world_store=$(field world_store)
|
||||
kernel_store=$(field kernel_store)
|
||||
headers_store=$(field headers_store)
|
||||
bootloader_store=$(field bootloader_store)
|
||||
|
||||
[ "$executor_kind" = ssh-guest ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; }
|
||||
[ "$executor_name" = ssh-guest ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; }
|
||||
[ "$executor_version" = 1 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; }
|
||||
[ "$artifact_store_count" = 4 ] || { echo "unexpected artifact store count: $artifact_store_count" >&2; exit 1; }
|
||||
case "$result_store" in
|
||||
/frx/store/*-fruix-native-build-result-*-ssh-guest) : ;;
|
||||
*) echo "unexpected result store path: $result_store" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$world_store" in
|
||||
/frx/store/*-fruix-native-world-*-ssh-guest) : ;;
|
||||
*) echo "unexpected world store path: $world_store" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$kernel_store" in
|
||||
/frx/store/*-fruix-native-kernel-*-ssh-guest) : ;;
|
||||
*) echo "unexpected kernel store path: $kernel_store" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$headers_store" in
|
||||
/frx/store/*-fruix-native-headers-*-ssh-guest) : ;;
|
||||
*) echo "unexpected headers store path: $headers_store" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$bootloader_store" in
|
||||
/frx/store/*-fruix-native-bootloader-*-ssh-guest) : ;;
|
||||
*) echo "unexpected bootloader store path: $bootloader_store" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
[ -f "$result_metadata_file" ] || { echo "missing result metadata file: $result_metadata_file" >&2; exit 1; }
|
||||
[ -f "$world_store/.fruix-native-build-object.scm" ] || { echo "missing world store metadata" >&2; exit 1; }
|
||||
[ -f "$kernel_store/.fruix-native-build-object.scm" ] || { echo "missing kernel store metadata" >&2; exit 1; }
|
||||
[ -f "$headers_store/.fruix-native-build-object.scm" ] || { echo "missing headers store metadata" >&2; exit 1; }
|
||||
[ -f "$bootloader_store/.fruix-native-build-object.scm" ] || { echo "missing bootloader store metadata" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/world" ] || { echo "missing promoted world artifact link" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/kernel" ] || { echo "missing promoted kernel artifact link" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/headers" ] || { echo "missing promoted headers artifact link" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/bootloader" ] || { echo "missing promoted bootloader artifact link" >&2; exit 1; }
|
||||
[ "$(readlink "$result_store/artifacts/world")" = "$world_store" ] || { echo "world artifact link mismatch" >&2; exit 1; }
|
||||
[ "$(readlink "$result_store/artifacts/kernel")" = "$kernel_store" ] || { echo "kernel artifact link mismatch" >&2; exit 1; }
|
||||
[ "$(readlink "$result_store/artifacts/headers")" = "$headers_store" ] || { echo "headers artifact link mismatch" >&2; exit 1; }
|
||||
[ "$(readlink "$result_store/artifacts/bootloader")" = "$bootloader_store" ] || { echo "bootloader artifact link mismatch" >&2; exit 1; }
|
||||
[ -f "$world_store/bin/sh" ] || { echo "promoted world store missing /bin/sh" >&2; exit 1; }
|
||||
[ -f "$kernel_store/boot/kernel/kernel" ] || { echo "promoted kernel store missing kernel" >&2; exit 1; }
|
||||
[ -f "$headers_store/usr/include/sys/param.h" ] || { echo "promoted headers store missing param.h" >&2; exit 1; }
|
||||
[ -f "$bootloader_store/boot/loader.efi" ] || { echo "promoted bootloader store missing loader.efi" >&2; exit 1; }
|
||||
|
||||
promoted_kernel_sha=$(sha256 -q "$kernel_store/boot/kernel/kernel")
|
||||
promoted_loader_sha=$(sha256 -q "$bootloader_store/boot/loader.efi")
|
||||
promoted_param_sha=$(sha256 -q "$headers_store/usr/include/sys/param.h")
|
||||
[ "$promoted_kernel_sha" = "$sha_kernel" ] || { echo "kernel sha mismatch after promotion" >&2; exit 1; }
|
||||
[ "$promoted_loader_sha" = "$sha_loader" ] || { echo "loader sha mismatch after promotion" >&2; exit 1; }
|
||||
[ "$promoted_param_sha" = "$sha_param" ] || { echo "param.h sha mismatch after promotion" >&2; exit 1; }
|
||||
|
||||
grep -F '(executor-kind . ssh-guest)' "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing ssh-guest executor kind" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F '(executor-name . "ssh-guest")' "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing ssh-guest executor name" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$source_store" "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing source store provenance" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F '(artifact-kind . kernel)' "$kernel_store/.fruix-native-build-object.scm" >/dev/null || {
|
||||
echo "kernel store metadata is missing artifact kind" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F '(artifact-kind . world)' "$world_store/.fruix-native-build-object.scm" >/dev/null || {
|
||||
echo "world store metadata is missing artifact kind" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cat >"$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
inner_metadata=$inner_metadata
|
||||
promotion_out=$promotion_out
|
||||
closure_path=$closure_path
|
||||
closure_base=$closure_base
|
||||
vm_id=$vm_id
|
||||
vdi_id=$vdi_id
|
||||
guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
run_id=$run_id
|
||||
source_store=$source_store
|
||||
guest_result_root=$result_root
|
||||
guest_promotion_file=$promotion_file
|
||||
guest_world_artifact=$world_artifact
|
||||
guest_kernel_artifact=$kernel_artifact
|
||||
guest_headers_artifact=$headers_artifact
|
||||
guest_bootloader_artifact=$bootloader_artifact
|
||||
local_result_root=$local_result_root
|
||||
store_dir=$store_dir
|
||||
executor_kind=$executor_kind
|
||||
executor_name=$executor_name
|
||||
executor_version=$executor_version
|
||||
result_store=$result_store
|
||||
result_metadata_file=$result_metadata_file
|
||||
artifact_store_count=$artifact_store_count
|
||||
artifact_stores=$artifact_stores
|
||||
world_store=$world_store
|
||||
kernel_store=$kernel_store
|
||||
headers_store=$headers_store
|
||||
bootloader_store=$bootloader_store
|
||||
sha_kernel=$sha_kernel
|
||||
sha_loader=$sha_loader
|
||||
sha_param=$sha_param
|
||||
promoted_kernel_sha=$promoted_kernel_sha
|
||||
promoted_loader_sha=$promoted_loader_sha
|
||||
promoted_param_sha=$promoted_param_sha
|
||||
boot_backend=xcp-ng-xo-cli
|
||||
init_mode=shepherd-pid1
|
||||
host_initiated_native_build_store_promotion=ok
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS phase20-host-initiated-native-build-store-promotion-xcpng\n'
|
||||
printf 'Work directory: %s\n' "$workdir"
|
||||
printf 'Metadata file: %s\n' "$metadata_file"
|
||||
if [ -n "$metadata_target" ]; then
|
||||
printf 'Copied metadata to: %s\n' "$metadata_target"
|
||||
fi
|
||||
printf '%s\n' '--- metadata ---'
|
||||
cat "$metadata_file"
|
||||
@@ -70,49 +70,76 @@ case "$guest_build_jobs" in
|
||||
;;
|
||||
esac
|
||||
|
||||
native_build_metadata=$(ssh_guest env BUILD_JOBS="$guest_build_jobs" sh -s <<'EOF'
|
||||
native_build_metadata=$(ssh_guest env BUILD_JOBS="$guest_build_jobs" GUEST_IP="$guest_ip" VM_ID="$vm_id" VDI_ID="$vdi_id" sh -s <<'EOF'
|
||||
set -eu
|
||||
[ -L /run/current-development ]
|
||||
[ -L /run/current-build ]
|
||||
[ -L /usr/include ]
|
||||
[ "$(readlink /usr/include)" = "/run/current-system/development-profile/usr/include" ]
|
||||
[ "$(readlink /usr/include)" = "/run/current-system/build-profile/usr/include" ]
|
||||
[ -L /usr/share/mk ]
|
||||
[ "$(readlink /usr/share/mk)" = "/run/current-system/development-profile/usr/share/mk" ]
|
||||
[ "$(readlink /usr/share/mk)" = "/run/current-system/build-profile/usr/share/mk" ]
|
||||
guest_host_name=$(hostname)
|
||||
closure=$(readlink /run/current-system)
|
||||
source_store=$(sed -n 's/.*"\(\/frx\/store\/[^\"]*-freebsd-source-[^\"]*\)".*/\1/p' "$closure/metadata/store-layout.scm" | head -n 1)
|
||||
source_store=$(sed -n 's/.*"\(\/frx\/store\/[^"]*-freebsd-source-[^"]*\)".*/\1/p' "$closure/metadata/store-layout.scm" | head -n 1)
|
||||
source_root="$source_store/tree"
|
||||
build_common='TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no'
|
||||
install_common="$build_common DB_FROM_SRC=yes"
|
||||
build_root=/var/tmp/fruix-phase20-native-build
|
||||
run_id=${FRUIX_HOST_INITIATED_NATIVE_BUILD_ID:-$(date -u +%Y%m%dT%H%M%SZ)}
|
||||
result_root_base=/var/lib/fruix/native-builds
|
||||
result_root=$result_root_base/$run_id
|
||||
logdir=$build_root/logs
|
||||
status_file=$result_root/status
|
||||
guest_metadata_file=$result_root/metadata.txt
|
||||
promotion_file=$result_root/promotion.scm
|
||||
world_stage=$build_root/stage-world
|
||||
kernel_stage=$build_root/stage-kernel
|
||||
headers_stage=$build_root/artifact-headers
|
||||
bootloader_stage=$build_root/artifact-bootloader
|
||||
rm -rf "$build_root"
|
||||
mkdir -p "$logdir"
|
||||
world_artifact=$result_root/artifacts/world
|
||||
kernel_artifact=$result_root/artifacts/kernel
|
||||
headers_artifact=$result_root/artifacts/headers
|
||||
bootloader_artifact=$result_root/artifacts/bootloader
|
||||
latest_link=$result_root_base/latest
|
||||
rm -rf "$build_root" "$result_root"
|
||||
mkdir -p "$logdir" "$result_root" "$world_artifact" "$kernel_artifact/boot" "$headers_artifact/usr" "$bootloader_artifact/boot"
|
||||
printf 'running\n' > "$status_file"
|
||||
fail_mark() {
|
||||
rc=$?
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
printf 'failed\n' > "$status_file"
|
||||
fi
|
||||
}
|
||||
trap fail_mark EXIT HUP INT TERM
|
||||
export MAKEOBJDIRPREFIX="$build_root/obj"
|
||||
common='TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no DB_FROM_SRC=yes'
|
||||
make -j"$BUILD_JOBS" -C "$source_root" TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no buildworld > "$logdir/buildworld.log" 2>&1
|
||||
make -j"$BUILD_JOBS" -C "$source_root" TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no buildkernel > "$logdir/buildkernel.log" 2>&1
|
||||
make -C "$source_root" $common DESTDIR="$world_stage" installworld > "$logdir/installworld.log" 2>&1
|
||||
make -C "$source_root" $common DESTDIR="$world_stage" distribution > "$logdir/distribution.log" 2>&1
|
||||
make -C "$source_root" $common DESTDIR="$kernel_stage" installkernel > "$logdir/installkernel.log" 2>&1
|
||||
make -C "$source_root" $install_common DESTDIR="$world_stage" installworld > "$logdir/installworld.log" 2>&1
|
||||
make -C "$source_root" $install_common DESTDIR="$world_stage" distribution > "$logdir/distribution.log" 2>&1
|
||||
make -C "$source_root" $install_common DESTDIR="$kernel_stage" installkernel > "$logdir/installkernel.log" 2>&1
|
||||
mkdir -p "$headers_stage/usr" "$bootloader_stage/boot"
|
||||
cp -a "$world_stage/." "$world_artifact/"
|
||||
cp -a "$kernel_stage/boot/kernel" "$kernel_artifact/boot/kernel"
|
||||
cp -a "$world_stage/usr/include" "$headers_stage/usr/include"
|
||||
mkdir -p "$headers_stage/usr/share"
|
||||
cp -a "$world_stage/usr/share/mk" "$headers_stage/usr/share/mk"
|
||||
cp -a "$headers_stage/usr/." "$headers_artifact/usr/"
|
||||
cp -a "$world_stage/boot/loader" "$bootloader_stage/boot/loader"
|
||||
cp -a "$world_stage/boot/loader.efi" "$bootloader_stage/boot/loader.efi"
|
||||
cp -a "$world_stage/boot/device.hints" "$bootloader_stage/boot/device.hints"
|
||||
cp -a "$world_stage/boot/defaults" "$bootloader_stage/boot/defaults"
|
||||
cp -a "$world_stage/boot/lua" "$bootloader_stage/boot/lua"
|
||||
[ -f "$kernel_stage/boot/kernel/kernel" ]
|
||||
[ -f "$headers_stage/usr/include/sys/param.h" ]
|
||||
[ -f "$headers_stage/usr/share/mk/bsd.prog.mk" ]
|
||||
[ -f "$bootloader_stage/boot/loader.efi" ]
|
||||
[ -f "$bootloader_stage/boot/defaults/loader.conf" ]
|
||||
[ -f "$bootloader_stage/boot/lua/loader.lua" ]
|
||||
sha_kernel=$(sha256 -q "$kernel_stage/boot/kernel/kernel")
|
||||
sha_loader=$(sha256 -q "$bootloader_stage/boot/loader.efi")
|
||||
sha_param=$(sha256 -q "$headers_stage/usr/include/sys/param.h")
|
||||
cp -a "$bootloader_stage/boot/." "$bootloader_artifact/boot/"
|
||||
[ -f "$world_artifact/bin/sh" ]
|
||||
[ -f "$kernel_artifact/boot/kernel/kernel" ]
|
||||
[ -f "$headers_artifact/usr/include/sys/param.h" ]
|
||||
[ -f "$headers_artifact/usr/share/mk/bsd.prog.mk" ]
|
||||
[ -f "$bootloader_artifact/boot/loader.efi" ]
|
||||
[ -f "$bootloader_artifact/boot/defaults/loader.conf" ]
|
||||
[ -f "$bootloader_artifact/boot/lua/loader.lua" ]
|
||||
sha_kernel=$(sha256 -q "$kernel_artifact/boot/kernel/kernel")
|
||||
sha_loader=$(sha256 -q "$bootloader_artifact/boot/loader.efi")
|
||||
sha_param=$(sha256 -q "$headers_artifact/usr/include/sys/param.h")
|
||||
buildworld_tail=$(tail -n 20 "$logdir/buildworld.log" | tr '\n' ' ')
|
||||
buildkernel_tail=$(tail -n 20 "$logdir/buildkernel.log" | tr '\n' ' ')
|
||||
installworld_tail=$(tail -n 20 "$logdir/installworld.log" | tr '\n' ' ')
|
||||
@@ -120,46 +147,131 @@ distribution_tail=$(tail -n 20 "$logdir/distribution.log" | tr '\n' ' ')
|
||||
installkernel_tail=$(tail -n 20 "$logdir/installkernel.log" | tr '\n' ' ')
|
||||
root_df=$(df -h / | tail -n 1 | tr -s ' ' | tr '\t' ' ')
|
||||
build_root_size=$(du -sh "$build_root" | awk '{print $1}')
|
||||
result_root_size=$(du -sh "$result_root" | awk '{print $1}')
|
||||
world_stage_size=$(du -sh "$world_stage" | awk '{print $1}')
|
||||
kernel_stage_size=$(du -sh "$kernel_stage" | awk '{print $1}')
|
||||
headers_stage_size=$(du -sh "$headers_stage" | awk '{print $1}')
|
||||
bootloader_stage_size=$(du -sh "$bootloader_stage" | awk '{print $1}')
|
||||
printf 'build_jobs=%s\n' "$BUILD_JOBS"
|
||||
printf 'source_store=%s\n' "$source_store"
|
||||
printf 'source_root=%s\n' "$source_root"
|
||||
printf 'build_root=%s\n' "$build_root"
|
||||
printf 'logdir=%s\n' "$logdir"
|
||||
printf 'buildworld_log=%s\n' "$logdir/buildworld.log"
|
||||
printf 'buildkernel_log=%s\n' "$logdir/buildkernel.log"
|
||||
printf 'installworld_log=%s\n' "$logdir/installworld.log"
|
||||
printf 'distribution_log=%s\n' "$logdir/distribution.log"
|
||||
printf 'installkernel_log=%s\n' "$logdir/installkernel.log"
|
||||
printf 'world_stage=%s\n' "$world_stage"
|
||||
printf 'kernel_stage=%s\n' "$kernel_stage"
|
||||
printf 'headers_stage=%s\n' "$headers_stage"
|
||||
printf 'bootloader_stage=%s\n' "$bootloader_stage"
|
||||
printf 'root_df=%s\n' "$root_df"
|
||||
printf 'build_root_size=%s\n' "$build_root_size"
|
||||
printf 'world_stage_size=%s\n' "$world_stage_size"
|
||||
printf 'kernel_stage_size=%s\n' "$kernel_stage_size"
|
||||
printf 'headers_stage_size=%s\n' "$headers_stage_size"
|
||||
printf 'bootloader_stage_size=%s\n' "$bootloader_stage_size"
|
||||
printf 'sha_kernel=%s\n' "$sha_kernel"
|
||||
printf 'sha_loader=%s\n' "$sha_loader"
|
||||
printf 'sha_param=%s\n' "$sha_param"
|
||||
printf 'buildworld_tail=%s\n' "$buildworld_tail"
|
||||
printf 'buildkernel_tail=%s\n' "$buildkernel_tail"
|
||||
printf 'installworld_tail=%s\n' "$installworld_tail"
|
||||
printf 'distribution_tail=%s\n' "$distribution_tail"
|
||||
printf 'installkernel_tail=%s\n' "$installkernel_tail"
|
||||
world_artifact_size=$(du -sh "$world_artifact" | awk '{print $1}')
|
||||
kernel_artifact_size=$(du -sh "$kernel_artifact" | awk '{print $1}')
|
||||
headers_artifact_size=$(du -sh "$headers_artifact" | awk '{print $1}')
|
||||
bootloader_artifact_size=$(du -sh "$bootloader_artifact" | awk '{print $1}')
|
||||
rm -f "$latest_link"
|
||||
ln -s "$result_root" "$latest_link"
|
||||
cat >"$promotion_file" <<EOF2
|
||||
((native-build-result-version . "1")
|
||||
(executor . ((kind . ssh-guest)
|
||||
(name . "ssh-guest")
|
||||
(version . "1")
|
||||
(properties . ((transport . "ssh")
|
||||
(orchestrator . "host")
|
||||
(guest-host-name . "$guest_host_name")
|
||||
(guest-ip . "$GUEST_IP")
|
||||
(vm-id . "$VM_ID")
|
||||
(vdi-id . "$VDI_ID")))))
|
||||
(run-id . "$run_id")
|
||||
(guest-host-name . "$guest_host_name")
|
||||
(closure-path . "$closure")
|
||||
(build-profile . "/run/current-system/build-profile")
|
||||
(freebsd-base . ((name . "default")
|
||||
(version-label . "15.0-STABLE")
|
||||
(release . "15.0-STABLE")
|
||||
(branch . "stable/15")
|
||||
(source-root . "/usr/src")
|
||||
(target . "amd64")
|
||||
(target-arch . "amd64")
|
||||
(kernconf . "GENERIC")))
|
||||
(source . ((store-path . "$source_store")
|
||||
(source-root . "$source_root")))
|
||||
(build-policy . ((jobs . "$BUILD_JOBS")
|
||||
(build-common . "$build_common")
|
||||
(install-common . "$install_common")))
|
||||
(artifacts . ((world . ((path . "artifacts/world")
|
||||
(required-file . "bin/sh")))
|
||||
(kernel . ((path . "artifacts/kernel")
|
||||
(required-file . "boot/kernel/kernel")
|
||||
(recorded-sha256 . "$sha_kernel")))
|
||||
(headers . ((path . "artifacts/headers")
|
||||
(required-file . "usr/include/sys/param.h")
|
||||
(recorded-sha256 . "$sha_param")))
|
||||
(bootloader . ((path . "artifacts/bootloader")
|
||||
(required-file . "boot/loader.efi")
|
||||
(recorded-sha256 . "$sha_loader"))))))
|
||||
EOF2
|
||||
cat >"$guest_metadata_file" <<EOF2
|
||||
run_id=$run_id
|
||||
executor_kind=ssh-guest
|
||||
executor_name=ssh-guest
|
||||
executor_version=1
|
||||
guest_host_name=$guest_host_name
|
||||
closure_path=$closure
|
||||
source_store=$source_store
|
||||
source_root=$source_root
|
||||
build_jobs=$BUILD_JOBS
|
||||
build_common=$build_common
|
||||
install_common=$install_common
|
||||
build_root=$build_root
|
||||
result_root=$result_root
|
||||
logdir=$logdir
|
||||
status_file=$status_file
|
||||
metadata_file=$guest_metadata_file
|
||||
promotion_file=$promotion_file
|
||||
world_stage=$world_stage
|
||||
kernel_stage=$kernel_stage
|
||||
headers_stage=$headers_stage
|
||||
bootloader_stage=$bootloader_stage
|
||||
world_artifact=$world_artifact
|
||||
kernel_artifact=$kernel_artifact
|
||||
headers_artifact=$headers_artifact
|
||||
bootloader_artifact=$bootloader_artifact
|
||||
latest_link=$latest_link
|
||||
root_df=$root_df
|
||||
build_root_size=$build_root_size
|
||||
result_root_size=$result_root_size
|
||||
world_stage_size=$world_stage_size
|
||||
kernel_stage_size=$kernel_stage_size
|
||||
headers_stage_size=$headers_stage_size
|
||||
bootloader_stage_size=$bootloader_stage_size
|
||||
world_artifact_size=$world_artifact_size
|
||||
kernel_artifact_size=$kernel_artifact_size
|
||||
headers_artifact_size=$headers_artifact_size
|
||||
bootloader_artifact_size=$bootloader_artifact_size
|
||||
buildworld_log=$logdir/buildworld.log
|
||||
buildkernel_log=$logdir/buildkernel.log
|
||||
installworld_log=$logdir/installworld.log
|
||||
distribution_log=$logdir/distribution.log
|
||||
installkernel_log=$logdir/installkernel.log
|
||||
sha_kernel=$sha_kernel
|
||||
sha_loader=$sha_loader
|
||||
sha_param=$sha_param
|
||||
buildworld_tail=$buildworld_tail
|
||||
buildkernel_tail=$buildkernel_tail
|
||||
installworld_tail=$installworld_tail
|
||||
distribution_tail=$distribution_tail
|
||||
installkernel_tail=$installkernel_tail
|
||||
host_initiated_native_build=ok
|
||||
EOF2
|
||||
printf 'ok\n' > "$status_file"
|
||||
cat "$guest_metadata_file"
|
||||
EOF
|
||||
)
|
||||
|
||||
build_jobs=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_jobs=//p')
|
||||
run_id=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^run_id=//p')
|
||||
executor_kind=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^executor_kind=//p')
|
||||
executor_name=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^executor_name=//p')
|
||||
executor_version=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^executor_version=//p')
|
||||
guest_host_name=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^guest_host_name=//p')
|
||||
source_store=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^source_store=//p')
|
||||
source_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^source_root=//p')
|
||||
build_jobs=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_jobs=//p')
|
||||
build_common=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_common=//p')
|
||||
install_common=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^install_common=//p')
|
||||
build_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_root=//p')
|
||||
result_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^result_root=//p')
|
||||
logdir=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^logdir=//p')
|
||||
status_file=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^status_file=//p')
|
||||
guest_metadata_file=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^metadata_file=//p')
|
||||
promotion_file=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^promotion_file=//p')
|
||||
buildworld_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildworld_log=//p')
|
||||
buildkernel_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildkernel_log=//p')
|
||||
installworld_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installworld_log=//p')
|
||||
@@ -169,12 +281,22 @@ world_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_stage=//
|
||||
kernel_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_stage=//p')
|
||||
headers_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_stage=//p')
|
||||
bootloader_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_stage=//p')
|
||||
world_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_artifact=//p')
|
||||
kernel_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_artifact=//p')
|
||||
headers_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_artifact=//p')
|
||||
bootloader_artifact=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_artifact=//p')
|
||||
latest_link=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^latest_link=//p')
|
||||
root_df=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^root_df=//p')
|
||||
build_root_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_root_size=//p')
|
||||
result_root_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^result_root_size=//p')
|
||||
world_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_stage_size=//p')
|
||||
kernel_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_stage_size=//p')
|
||||
headers_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_stage_size=//p')
|
||||
bootloader_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_stage_size=//p')
|
||||
world_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_artifact_size=//p')
|
||||
kernel_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_artifact_size=//p')
|
||||
headers_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_artifact_size=//p')
|
||||
bootloader_artifact_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_artifact_size=//p')
|
||||
sha_kernel=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_kernel=//p')
|
||||
sha_loader=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_loader=//p')
|
||||
sha_param=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_param=//p')
|
||||
@@ -184,6 +306,17 @@ installworld_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installw
|
||||
distribution_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^distribution_tail=//p')
|
||||
installkernel_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installkernel_tail=//p')
|
||||
|
||||
status_value=$(ssh_guest "cat '$status_file'")
|
||||
latest_target=$(ssh_guest "readlink '$latest_link'")
|
||||
ssh_guest "[ -f '$promotion_file' ]"
|
||||
ssh_guest "[ -f '$world_artifact/bin/sh' ]"
|
||||
|
||||
[ "$executor_kind" = ssh-guest ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; }
|
||||
[ "$executor_name" = ssh-guest ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; }
|
||||
[ "$executor_version" = 1 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; }
|
||||
[ "$status_value" = ok ] || { echo "host-initiated build status is not ok: $status_value" >&2; exit 1; }
|
||||
[ "$latest_target" = "$result_root" ] || { echo "latest link target mismatch: $latest_target" >&2; exit 1; }
|
||||
|
||||
case "$source_store" in
|
||||
/frx/store/*-freebsd-source-*) : ;;
|
||||
*) echo "unexpected source store path: $source_store" >&2; exit 1 ;;
|
||||
@@ -196,6 +329,10 @@ case "$build_root" in
|
||||
/var/tmp/fruix-phase20-native-build) : ;;
|
||||
*) echo "unexpected build root: $build_root" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$result_root" in
|
||||
/var/lib/fruix/native-builds/*) : ;;
|
||||
*) echo "unexpected result root: $result_root" >&2; exit 1 ;;
|
||||
esac
|
||||
printf '%s\n' "$sha_kernel" | grep -E '^[0-9a-f]{64}$' >/dev/null || {
|
||||
echo "invalid kernel sha256: $sha_kernel" >&2
|
||||
exit 1
|
||||
@@ -227,11 +364,22 @@ vm_id=$vm_id
|
||||
vdi_id=$vdi_id
|
||||
guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
run_id=$run_id
|
||||
executor_kind=$executor_kind
|
||||
executor_name=$executor_name
|
||||
executor_version=$executor_version
|
||||
guest_host_name=$guest_host_name
|
||||
build_jobs=$build_jobs
|
||||
source_store=$source_store
|
||||
source_root=$source_root
|
||||
build_common=$build_common
|
||||
install_common=$install_common
|
||||
build_root=$build_root
|
||||
result_root=$result_root
|
||||
logdir=$logdir
|
||||
status_file=$status_file
|
||||
guest_metadata_file=$guest_metadata_file
|
||||
promotion_file=$promotion_file
|
||||
buildworld_log=$buildworld_log
|
||||
buildkernel_log=$buildkernel_log
|
||||
installworld_log=$installworld_log
|
||||
@@ -241,12 +389,24 @@ world_stage=$world_stage
|
||||
kernel_stage=$kernel_stage
|
||||
headers_stage=$headers_stage
|
||||
bootloader_stage=$bootloader_stage
|
||||
world_artifact=$world_artifact
|
||||
kernel_artifact=$kernel_artifact
|
||||
headers_artifact=$headers_artifact
|
||||
bootloader_artifact=$bootloader_artifact
|
||||
latest_link=$latest_link
|
||||
latest_target=$latest_target
|
||||
status_value=$status_value
|
||||
root_df=$root_df
|
||||
build_root_size=$build_root_size
|
||||
result_root_size=$result_root_size
|
||||
world_stage_size=$world_stage_size
|
||||
kernel_stage_size=$kernel_stage_size
|
||||
headers_stage_size=$headers_stage_size
|
||||
bootloader_stage_size=$bootloader_stage_size
|
||||
world_artifact_size=$world_artifact_size
|
||||
kernel_artifact_size=$kernel_artifact_size
|
||||
headers_artifact_size=$headers_artifact_size
|
||||
bootloader_artifact_size=$bootloader_artifact_size
|
||||
sha_kernel=$sha_kernel
|
||||
sha_loader=$sha_loader
|
||||
sha_param=$sha_param
|
||||
|
||||
@@ -104,6 +104,9 @@ field() {
|
||||
sed -n "s/^$1=//p" "$promotion_out" | tail -n 1
|
||||
}
|
||||
|
||||
executor_kind=$(field executor_kind)
|
||||
executor_name=$(field executor_name)
|
||||
executor_version=$(field executor_version)
|
||||
result_store=$(field result_store)
|
||||
result_metadata_file=$(field result_metadata_file)
|
||||
artifact_store_count=$(field artifact_store_count)
|
||||
@@ -113,6 +116,9 @@ kernel_store=$(field kernel_store)
|
||||
headers_store=$(field headers_store)
|
||||
bootloader_store=$(field bootloader_store)
|
||||
|
||||
[ "$executor_kind" = self-hosted ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; }
|
||||
[ "$executor_name" = guest-self-hosted ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; }
|
||||
[ "$executor_version" = 5 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; }
|
||||
[ "$artifact_store_count" = 4 ] || { echo "unexpected artifact store count: $artifact_store_count" >&2; exit 1; }
|
||||
case "$result_store" in
|
||||
/frx/store/*-fruix-native-build-result-*-guest-self-hosted) : ;;
|
||||
@@ -160,14 +166,22 @@ promoted_param_sha=$(sha256 -q "$headers_store/usr/include/sys/param.h")
|
||||
[ "$promoted_loader_sha" = "$sha_loader" ] || { echo "loader sha mismatch after promotion" >&2; exit 1; }
|
||||
[ "$promoted_param_sha" = "$sha_param" ] || { echo "param.h sha mismatch after promotion" >&2; exit 1; }
|
||||
|
||||
grep -F '(executor . "guest-self-hosted")' "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing guest-self-hosted executor" >&2
|
||||
grep -F '(executor-kind . self-hosted)' "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing self-hosted executor kind" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F '(executor-name . "guest-self-hosted")' "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing guest-self-hosted executor name" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$source_store" "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing source store provenance" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F '(build-profile . "/run/current-system/build-profile")' "$result_metadata_file" >/dev/null || {
|
||||
echo "result metadata file is missing build-profile provenance" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F '(artifact-kind . kernel)' "$kernel_store/.fruix-native-build-object.scm" >/dev/null || {
|
||||
echo "kernel store metadata is missing artifact kind" >&2
|
||||
exit 1
|
||||
@@ -197,6 +211,9 @@ guest_headers_artifact=$headers_artifact
|
||||
guest_bootloader_artifact=$bootloader_artifact
|
||||
local_result_root=$local_result_root
|
||||
store_dir=$store_dir
|
||||
executor_kind=$executor_kind
|
||||
executor_name=$executor_name
|
||||
executor_version=$executor_version
|
||||
result_store=$result_store
|
||||
result_metadata_file=$result_metadata_file
|
||||
artifact_store_count=$artifact_store_count
|
||||
|
||||
227
tests/system/run-phase20-promoted-native-base-declaration-xcpng.sh
Executable file
227
tests/system/run-phase20-promoted-native-base-declaration-xcpng.sh
Executable file
@@ -0,0 +1,227 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo_root=${PROJECT_ROOT:-$(pwd)}
|
||||
os_template=${OS_TEMPLATE:-$repo_root/tests/system/phase20-promoted-native-base-operating-system.scm.in}
|
||||
system_name=${SYSTEM_NAME:-phase20-promoted-native-base-operating-system}
|
||||
root_size=${ROOT_SIZE:-12g}
|
||||
result_store=${RESULT_STORE:-}
|
||||
metadata_target=${METADATA_OUT:-}
|
||||
root_authorized_key_file=${ROOT_AUTHORIZED_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}
|
||||
root_ssh_private_key_file=${ROOT_SSH_PRIVATE_KEY_FILE:-$HOME/.ssh/id_ed25519}
|
||||
cleanup=0
|
||||
|
||||
if [ -n "${WORKDIR:-}" ]; then
|
||||
workdir=$WORKDIR
|
||||
mkdir -p "$workdir"
|
||||
else
|
||||
workdir=$(mktemp -d /tmp/fruix-phase20-promoted-native-base-xcpng.XXXXXX)
|
||||
cleanup=1
|
||||
fi
|
||||
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
||||
cleanup=0
|
||||
fi
|
||||
|
||||
promotion_metadata=$workdir/phase20-promoted-native-base-promotion-metadata.txt
|
||||
prepared_template=$workdir/phase20-promoted-native-base-operating-system.scm.in
|
||||
inner_metadata=$workdir/phase20-promoted-native-base-inner-metadata.txt
|
||||
metadata_file=$workdir/phase20-promoted-native-base-declaration-xcpng-metadata.txt
|
||||
|
||||
cleanup_workdir() {
|
||||
if [ "$cleanup" -eq 1 ]; then
|
||||
rm -rf "$workdir"
|
||||
fi
|
||||
}
|
||||
trap cleanup_workdir EXIT INT TERM
|
||||
|
||||
if [ -z "$result_store" ]; then
|
||||
KEEP_WORKDIR=1 WORKDIR="$workdir/promotion" METADATA_OUT="$promotion_metadata" \
|
||||
ROOT_AUTHORIZED_KEY_FILE="$root_authorized_key_file" \
|
||||
ROOT_SSH_PRIVATE_KEY_FILE="$root_ssh_private_key_file" \
|
||||
ROOT_SIZE=20g \
|
||||
"$repo_root/tests/system/run-phase20-host-initiated-native-build-store-promotion-xcpng.sh"
|
||||
result_store=$(sed -n 's/^result_store=//p' "$promotion_metadata")
|
||||
fi
|
||||
|
||||
[ -n "$result_store" ] || { echo "missing promoted result store" >&2; exit 1; }
|
||||
[ -d "$result_store" ] || { echo "promoted result store does not exist: $result_store" >&2; exit 1; }
|
||||
[ -f "$result_store/.fruix-native-build-result.scm" ] || {
|
||||
echo "promoted result store is missing .fruix-native-build-result.scm" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -L "$result_store/artifacts/world" ] || { echo "promoted result store is missing world artifact link" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/kernel" ] || { echo "promoted result store is missing kernel artifact link" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/headers" ] || { echo "promoted result store is missing headers artifact link" >&2; exit 1; }
|
||||
[ -L "$result_store/artifacts/bootloader" ] || { echo "promoted result store is missing bootloader artifact link" >&2; exit 1; }
|
||||
|
||||
world_store=$(readlink "$result_store/artifacts/world")
|
||||
kernel_store=$(readlink "$result_store/artifacts/kernel")
|
||||
headers_store=$(readlink "$result_store/artifacts/headers")
|
||||
bootloader_store=$(readlink "$result_store/artifacts/bootloader")
|
||||
result_metadata_file=$result_store/.fruix-native-build-result.scm
|
||||
executor_kind=$(grep -o '(executor-kind \. [^)]*)' "$result_metadata_file" | head -n 1 | sed 's/(executor-kind \. //; s/)$//')
|
||||
executor_name=$(grep -o '(executor-name \. "[^"]*")' "$result_metadata_file" | head -n 1 | sed 's/(executor-name \. "//; s/")$//')
|
||||
executor_version=$(grep -o '(executor-version \. "[^"]*")' "$result_metadata_file" | head -n 1 | sed 's/(executor-version \. "//; s/")$//')
|
||||
|
||||
[ -f "$world_store/bin/sh" ] || { echo "promoted world store is missing /bin/sh" >&2; exit 1; }
|
||||
[ -f "$kernel_store/boot/kernel/kernel" ] || { echo "promoted kernel store is missing kernel" >&2; exit 1; }
|
||||
[ -f "$headers_store/usr/include/sys/param.h" ] || { echo "promoted headers store is missing param.h" >&2; exit 1; }
|
||||
[ -f "$bootloader_store/boot/loader.efi" ] || { echo "promoted bootloader store is missing loader.efi" >&2; exit 1; }
|
||||
|
||||
sed "s|__PROMOTED_RESULT_STORE__|$result_store|g" "$os_template" > "$prepared_template"
|
||||
|
||||
action_metadata=${promotion_metadata:-}
|
||||
ROOT_SIZE="$root_size" KEEP_WORKDIR=1 WORKDIR="$workdir/boot" METADATA_OUT="$inner_metadata" \
|
||||
ROOT_AUTHORIZED_KEY_FILE="$root_authorized_key_file" \
|
||||
ROOT_SSH_PRIVATE_KEY_FILE="$root_ssh_private_key_file" \
|
||||
OS_TEMPLATE="$prepared_template" SYSTEM_NAME="$system_name" \
|
||||
"$repo_root/tests/system/run-phase11-shepherd-pid1-xcpng.sh"
|
||||
|
||||
phase8_metadata=$(sed -n 's/^phase8_metadata=//p' "$inner_metadata")
|
||||
closure_path=$(sed -n 's/^closure_path=//p' "$inner_metadata")
|
||||
closure_base=$(sed -n 's/^closure_base=//p' "$inner_metadata")
|
||||
guest_ip=$(sed -n 's/^guest_ip=//p' "$inner_metadata")
|
||||
vm_id=$(sed -n 's/^vm_id=//p' "$inner_metadata")
|
||||
vdi_id=$(sed -n 's/^vdi_id=//p' "$inner_metadata")
|
||||
shepherd_pid=$(sed -n 's/^shepherd_pid=//p' "$inner_metadata")
|
||||
sshd_status=$(sed -n 's/^sshd_status=//p' "$inner_metadata")
|
||||
compat_prefix_shims=$(sed -n 's/^compat_prefix_shims=//p' "$inner_metadata")
|
||||
guile_module_smoke=$(sed -n 's/^guile_module_smoke=//p' "$inner_metadata")
|
||||
activate_log=$(sed -n 's/^activate_log=//p' "$inner_metadata")
|
||||
|
||||
promoted_result_file=$closure_path/metadata/promoted-native-build-result.scm
|
||||
store_layout_file=$closure_path/metadata/store-layout.scm
|
||||
|
||||
[ "$shepherd_pid" = 1 ] || { echo "shepherd was not PID 1" >&2; exit 1; }
|
||||
[ "$sshd_status" = running ] || { echo "sshd is not running" >&2; exit 1; }
|
||||
[ "$compat_prefix_shims" = absent ] || { echo "compatibility prefix shims reappeared" >&2; exit 1; }
|
||||
[ "$guile_module_smoke" = ok ] || { echo "guest Guile module smoke failed" >&2; exit 1; }
|
||||
case "$activate_log" in
|
||||
*fruix-activate:done*) : ;;
|
||||
*) echo "activation log does not show success" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
[ -f "$promoted_result_file" ] || { echo "closure is missing promoted native build result metadata" >&2; exit 1; }
|
||||
[ -f "$store_layout_file" ] || { echo "closure is missing store layout metadata" >&2; exit 1; }
|
||||
grep -F "$result_store" "$promoted_result_file" >/dev/null || {
|
||||
echo "closure promoted result metadata does not reference the selected result store" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$result_store" "$closure_path/.references" >/dev/null || {
|
||||
echo "closure references do not retain the promoted result store" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$kernel_store" "$promoted_result_file" >/dev/null || {
|
||||
echo "closure promoted result metadata does not reference the promoted kernel store" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$bootloader_store" "$promoted_result_file" >/dev/null || {
|
||||
echo "closure promoted result metadata does not reference the promoted bootloader store" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$result_store" "$store_layout_file" >/dev/null || {
|
||||
echo "store layout metadata does not record the promoted result store" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
kernel_link=$(readlink "$closure_path/boot/kernel/kernel")
|
||||
bootloader_link=$(readlink "$closure_path/boot/loader.efi")
|
||||
[ "$kernel_link" = "$kernel_store/boot/kernel/kernel" ] || {
|
||||
echo "closure kernel link does not target the promoted kernel store" >&2
|
||||
exit 1
|
||||
}
|
||||
[ "$bootloader_link" = "$bootloader_store/boot/loader.efi" ] || {
|
||||
echo "closure bootloader link does not target the promoted bootloader store" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
ssh_guest() {
|
||||
ssh -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
root@"$guest_ip" "$@"
|
||||
}
|
||||
|
||||
guest_promoted_metadata=$(ssh -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
root@"$guest_ip" 'sh -s' <<EOF
|
||||
set -eu
|
||||
[ -f /run/current-system/metadata/promoted-native-build-result.scm ]
|
||||
grep -F '$result_store' /run/current-system/metadata/promoted-native-build-result.scm >/dev/null
|
||||
grep -F '$result_store' /run/current-system/.references >/dev/null
|
||||
kernel_link=$(readlink /run/current-system/boot/kernel/kernel)
|
||||
bootloader_link=$(readlink /run/current-system/boot/loader.efi)
|
||||
[ "$kernel_link" = "$kernel_store/boot/kernel/kernel" ]
|
||||
[ "$bootloader_link" = "$bootloader_store/boot/loader.efi" ]
|
||||
[ -x /bin/sh ]
|
||||
[ -x /usr/sbin/sshd ]
|
||||
printf 'kernel_link=%s\n' "$kernel_link"
|
||||
printf 'bootloader_link=%s\n' "$bootloader_link"
|
||||
printf 'uname=%s\n' "$(uname -sr)"
|
||||
printf 'promoted_result_store=%s\n' '$result_store'
|
||||
EOF
|
||||
)
|
||||
|
||||
guest_kernel_link=$(printf '%s\n' "$guest_promoted_metadata" | sed -n 's/^kernel_link=//p')
|
||||
guest_bootloader_link=$(printf '%s\n' "$guest_promoted_metadata" | sed -n 's/^bootloader_link=//p')
|
||||
guest_uname=$(printf '%s\n' "$guest_promoted_metadata" | sed -n 's/^uname=//p')
|
||||
|
||||
[ "$guest_kernel_link" = "$kernel_store/boot/kernel/kernel" ] || {
|
||||
echo "guest kernel link does not target the promoted kernel store" >&2
|
||||
exit 1
|
||||
}
|
||||
[ "$guest_bootloader_link" = "$bootloader_store/boot/loader.efi" ] || {
|
||||
echo "guest bootloader link does not target the promoted bootloader store" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cat >"$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
promotion_metadata=$promotion_metadata
|
||||
inner_metadata=$inner_metadata
|
||||
phase8_metadata=$phase8_metadata
|
||||
closure_path=$closure_path
|
||||
closure_base=$closure_base
|
||||
vm_id=$vm_id
|
||||
vdi_id=$vdi_id
|
||||
guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
result_store=$result_store
|
||||
result_metadata_file=$result_metadata_file
|
||||
executor_kind=$executor_kind
|
||||
executor_name=$executor_name
|
||||
executor_version=$executor_version
|
||||
world_store=$world_store
|
||||
kernel_store=$kernel_store
|
||||
headers_store=$headers_store
|
||||
bootloader_store=$bootloader_store
|
||||
promoted_result_file=$promoted_result_file
|
||||
store_layout_file=$store_layout_file
|
||||
kernel_link=$kernel_link
|
||||
bootloader_link=$bootloader_link
|
||||
guest_kernel_link=$guest_kernel_link
|
||||
guest_bootloader_link=$guest_bootloader_link
|
||||
guest_uname=$guest_uname
|
||||
boot_backend=xcp-ng-xo-cli
|
||||
init_mode=shepherd-pid1
|
||||
promoted_native_base_declaration=ok
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS phase20-promoted-native-base-declaration-xcpng\n'
|
||||
printf 'Work directory: %s\n' "$workdir"
|
||||
printf 'Metadata file: %s\n' "$metadata_file"
|
||||
if [ -n "$metadata_target" ]; then
|
||||
printf 'Copied metadata to: %s\n' "$metadata_target"
|
||||
fi
|
||||
printf '%s\n' '--- metadata ---'
|
||||
cat "$metadata_file"
|
||||
@@ -70,7 +70,9 @@ case "$guest_build_jobs" in
|
||||
;;
|
||||
esac
|
||||
|
||||
ssh_guest '[ -x /usr/local/bin/fruix-build-environment ]'
|
||||
ssh_guest '[ -x /usr/local/bin/fruix-self-hosted-native-build ]'
|
||||
ssh_guest '[ -L /run/current-build ]'
|
||||
ssh_guest '[ -L /usr/include ]'
|
||||
ssh_guest '[ -L /usr/share/mk ]'
|
||||
|
||||
@@ -78,6 +80,10 @@ self_hosted_metadata=$(ssh_guest env FRUIX_SELF_HOSTED_NATIVE_BUILD_JOBS="$guest
|
||||
|
||||
run_id=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^run_id=//p')
|
||||
helper_version=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^helper_version=//p')
|
||||
executor_kind=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^executor_kind=//p')
|
||||
executor_name=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^executor_name=//p')
|
||||
executor_version=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^executor_version=//p')
|
||||
build_profile=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_profile=//p')
|
||||
source_store=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^source_store=//p')
|
||||
source_root=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^source_root=//p')
|
||||
build_jobs=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_jobs=//p')
|
||||
@@ -118,7 +124,11 @@ latest_target=$(ssh_guest "readlink '$latest_link'")
|
||||
ssh_guest "[ -f '$promotion_file' ]"
|
||||
ssh_guest "[ -f '$world_artifact/bin/sh' ]"
|
||||
|
||||
[ "$helper_version" = 3 ] || { echo "unexpected helper version: $helper_version" >&2; exit 1; }
|
||||
[ "$helper_version" = 5 ] || { echo "unexpected helper version: $helper_version" >&2; exit 1; }
|
||||
[ "$executor_kind" = self-hosted ] || { echo "unexpected executor kind: $executor_kind" >&2; exit 1; }
|
||||
[ "$executor_name" = guest-self-hosted ] || { echo "unexpected executor name: $executor_name" >&2; exit 1; }
|
||||
[ "$executor_version" = 5 ] || { echo "unexpected executor version: $executor_version" >&2; exit 1; }
|
||||
[ "$build_profile" = /run/current-system/build-profile ] || { echo "unexpected build profile: $build_profile" >&2; exit 1; }
|
||||
[ "$build_jobs" = "$guest_build_jobs" ] || { echo "unexpected build job count: $build_jobs" >&2; exit 1; }
|
||||
[ "$status_value" = ok ] || { echo "self-hosted build status is not ok: $status_value" >&2; exit 1; }
|
||||
[ "$latest_target" = "$result_root" ] || { echo "latest link target mismatch: $latest_target" >&2; exit 1; }
|
||||
@@ -197,7 +207,11 @@ guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
run_id=$run_id
|
||||
helper_version=$helper_version
|
||||
executor_kind=$executor_kind
|
||||
executor_name=$executor_name
|
||||
executor_version=$executor_version
|
||||
build_jobs=$build_jobs
|
||||
build_profile=$build_profile
|
||||
source_store=$source_store
|
||||
source_root=$source_root
|
||||
build_common=$build_common
|
||||
|
||||
@@ -104,11 +104,11 @@ image_size_bytes=$(stat -f '%z' "$disk_image")
|
||||
closure_base=$(basename "$closure_path")
|
||||
|
||||
case "$image_store_path" in
|
||||
/frx/store/*-fruix-bhyve-image-fruix-freebsd) : ;;
|
||||
/frx/store/*-fruix-bhyve-image-*) : ;;
|
||||
*) echo "unexpected image store path: $image_store_path" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$disk_image" in
|
||||
/frx/store/*-fruix-bhyve-image-fruix-freebsd/disk.img) : ;;
|
||||
/frx/store/*-fruix-bhyve-image-*/disk.img) : ;;
|
||||
*) echo "unexpected disk image path: $disk_image" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
@@ -142,7 +142,7 @@ if [ -L "$mnt_root/etc/master.passwd" ]; then master_passwd_kind=symlink; elif [
|
||||
loader_conf_image=$mnt_root/frx/store/$closure_base/boot/loader.conf
|
||||
rc_conf_image=$mnt_root/frx/store/$closure_base/etc/rc.conf
|
||||
grep -F 'comconsole' "$loader_conf_image" >/dev/null || { echo "loader.conf is missing serial console config" >&2; exit 1; }
|
||||
grep -F 'hostname="fruix-freebsd"' "$rc_conf_image" >/dev/null || { echo "rc.conf is missing hostname" >&2; exit 1; }
|
||||
grep -E '^hostname=".+"$' "$rc_conf_image" >/dev/null || { echo "rc.conf is missing hostname" >&2; exit 1; }
|
||||
[ -f "$host_base_provenance_file" ] || { echo "missing host base provenance file: $host_base_provenance_file" >&2; exit 1; }
|
||||
[ -f "$store_layout_file" ] || { echo "missing store layout file: $store_layout_file" >&2; exit 1; }
|
||||
[ -n "$host_freebsd_version" ] || { echo "missing host freebsd version provenance" >&2; exit 1; }
|
||||
|
||||
271
tests/system/run-postphase20-installed-node-build-reconfigure-xcpng.sh
Executable file
271
tests/system/run-postphase20-installed-node-build-reconfigure-xcpng.sh
Executable file
@@ -0,0 +1,271 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo_root=${PROJECT_ROOT:-$(pwd)}
|
||||
os_template=${OS_TEMPLATE:-$repo_root/tests/system/postphase20-installed-node-operating-system.scm.in}
|
||||
system_name=${SYSTEM_NAME:-postphase20-installed-node-operating-system}
|
||||
result_store=${RESULT_STORE:-/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest}
|
||||
root_size=${ROOT_SIZE:-12g}
|
||||
current_host_name=${CURRENT_HOST_NAME:-fruix-node-current}
|
||||
candidate_host_name=${CANDIDATE_HOST_NAME:-fruix-node-canary}
|
||||
metadata_target=${METADATA_OUT:-}
|
||||
root_authorized_key_file=${ROOT_AUTHORIZED_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}
|
||||
root_ssh_private_key_file=${ROOT_SSH_PRIVATE_KEY_FILE:-$HOME/.ssh/id_ed25519}
|
||||
cleanup=0
|
||||
|
||||
if [ -n "${WORKDIR:-}" ]; then
|
||||
workdir=$WORKDIR
|
||||
mkdir -p "$workdir"
|
||||
else
|
||||
workdir=$(mktemp -d /tmp/fruix-postphase20-installed-node-xcpng.XXXXXX)
|
||||
cleanup=1
|
||||
fi
|
||||
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
||||
cleanup=0
|
||||
fi
|
||||
|
||||
current_os_file=$workdir/current-operating-system.scm
|
||||
candidate_os_file=$workdir/candidate-operating-system.scm
|
||||
inner_metadata=$workdir/postphase20-installed-node-inner-metadata.txt
|
||||
current_build_out=$workdir/current-build.txt
|
||||
candidate_build_out=$workdir/candidate-build.txt
|
||||
reconfigure_out=$workdir/reconfigure.txt
|
||||
rollback_out=$workdir/rollback.txt
|
||||
post_reconfigure_status=$workdir/post-reconfigure-status.txt
|
||||
post_boot_candidate_status=$workdir/post-boot-candidate-status.txt
|
||||
post_boot_rollback_status=$workdir/post-boot-rollback-status.txt
|
||||
metadata_file=$workdir/postphase20-installed-node-build-reconfigure-xcpng-metadata.txt
|
||||
|
||||
cleanup_workdir() {
|
||||
if [ "$cleanup" -eq 1 ]; then
|
||||
rm -rf "$workdir"
|
||||
fi
|
||||
}
|
||||
trap cleanup_workdir EXIT INT TERM
|
||||
|
||||
[ -f "$os_template" ] || { echo "missing operating-system template: $os_template" >&2; exit 1; }
|
||||
[ -f "$root_authorized_key_file" ] || { echo "missing root authorized key file: $root_authorized_key_file" >&2; exit 1; }
|
||||
[ -f "$root_ssh_private_key_file" ] || { echo "missing root SSH private key file: $root_ssh_private_key_file" >&2; exit 1; }
|
||||
[ -d "$result_store" ] || { echo "promoted result store does not exist: $result_store" >&2; exit 1; }
|
||||
|
||||
root_authorized_key=$(tr -d '\n' < "$root_authorized_key_file")
|
||||
|
||||
render_os() {
|
||||
output=$1
|
||||
host_name=$2
|
||||
sed \
|
||||
-e "s|__PROMOTED_RESULT_STORE__|$result_store|g" \
|
||||
-e "s|__HOST_NAME__|$host_name|g" \
|
||||
-e "s|__ROOT_AUTHORIZED_KEY__|$root_authorized_key|g" \
|
||||
"$os_template" > "$output"
|
||||
}
|
||||
|
||||
render_os "$current_os_file" "$current_host_name"
|
||||
render_os "$candidate_os_file" "$candidate_host_name"
|
||||
|
||||
KEEP_WORKDIR=1 WORKDIR="$workdir/boot" METADATA_OUT="$inner_metadata" \
|
||||
ROOT_AUTHORIZED_KEY_FILE="$root_authorized_key_file" \
|
||||
ROOT_SSH_PRIVATE_KEY_FILE="$root_ssh_private_key_file" \
|
||||
OS_TEMPLATE="$current_os_file" SYSTEM_NAME="$system_name" ROOT_SIZE="$root_size" \
|
||||
"$repo_root/tests/system/run-phase11-shepherd-pid1-xcpng.sh"
|
||||
|
||||
phase8_metadata=$(sed -n 's/^phase8_metadata=//p' "$inner_metadata")
|
||||
closure_path=$(sed -n 's/^closure_path=//p' "$inner_metadata")
|
||||
closure_base=$(sed -n 's/^closure_base=//p' "$inner_metadata")
|
||||
guest_ip=$(sed -n 's/^guest_ip=//p' "$inner_metadata")
|
||||
vm_id=$(sed -n 's/^vm_id=//p' "$inner_metadata")
|
||||
vdi_id=$(sed -n 's/^vdi_id=//p' "$inner_metadata")
|
||||
shepherd_pid=$(sed -n 's/^shepherd_pid=//p' "$inner_metadata")
|
||||
sshd_status=$(sed -n 's/^sshd_status=//p' "$inner_metadata")
|
||||
compat_prefix_shims=$(sed -n 's/^compat_prefix_shims=//p' "$inner_metadata")
|
||||
guile_module_smoke=$(sed -n 's/^guile_module_smoke=//p' "$inner_metadata")
|
||||
activate_log=$(sed -n 's/^activate_log=//p' "$inner_metadata")
|
||||
|
||||
[ "$shepherd_pid" = 1 ] || { echo "shepherd was not PID 1" >&2; exit 1; }
|
||||
[ "$sshd_status" = running ] || { echo "sshd is not running" >&2; exit 1; }
|
||||
[ "$compat_prefix_shims" = absent ] || { echo "compatibility prefix shims reappeared" >&2; exit 1; }
|
||||
[ "$guile_module_smoke" = ok ] || { echo "guest Guile module smoke failed" >&2; exit 1; }
|
||||
case "$activate_log" in
|
||||
*fruix-activate:done*) : ;;
|
||||
*) echo "activation log does not show success" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
for path in \
|
||||
"$closure_path/metadata/system-declaration.scm" \
|
||||
"$closure_path/metadata/system-declaration-info.scm" \
|
||||
"$closure_path/metadata/system-declaration-system" \
|
||||
"$closure_path/share/fruix/node/scripts/fruix.scm" \
|
||||
"$closure_path/share/fruix/node/modules/fruix/system/freebsd/render.scm" \
|
||||
"$closure_path/share/fruix/node/guix/guix/build/utils.scm"
|
||||
do
|
||||
[ -f "$path" ] || {
|
||||
echo "required installed-node path missing: $path" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
grep -F "$current_host_name" "$closure_path/metadata/system-declaration.scm" >/dev/null || {
|
||||
echo "embedded declaration does not mention current host name" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -F "$system_name" "$closure_path/metadata/system-declaration-system" >/dev/null || {
|
||||
echo "embedded declaration system name is missing" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
ssh_guest() {
|
||||
ssh -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
root@"$guest_ip" "$@"
|
||||
}
|
||||
|
||||
scp_guest() {
|
||||
scp -O -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
"$@"
|
||||
}
|
||||
|
||||
wait_for_ssh() {
|
||||
for attempt in $(jot 120 1 120); do
|
||||
if ssh_guest 'service sshd onestatus >/dev/null 2>&1' >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
reboot_guest() {
|
||||
ssh_guest 'shutdown -r now >/dev/null 2>&1 || reboot >/dev/null 2>&1 || true' >/dev/null 2>&1 || true
|
||||
sleep 5
|
||||
wait_for_ssh || {
|
||||
echo "guest did not return over SSH after reboot" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
ssh_guest 'sh -s' <<EOF
|
||||
set -eu
|
||||
[ -x /usr/local/bin/fruix ]
|
||||
[ -f /run/current-system/metadata/system-declaration.scm ]
|
||||
[ -f /run/current-system/metadata/system-declaration-info.scm ]
|
||||
[ -f /run/current-system/metadata/system-declaration-system ]
|
||||
[ -f /run/current-system/share/fruix/node/scripts/fruix.scm ]
|
||||
[ -f /run/current-system/share/fruix/node/modules/fruix/system/freebsd/media.scm ]
|
||||
[ -f /run/current-system/share/fruix/node/guix/guix/build/utils.scm ]
|
||||
grep -F '$system_name' /run/current-system/metadata/system-declaration-system >/dev/null
|
||||
EOF
|
||||
|
||||
ssh_guest '/usr/local/bin/fruix system build' > "$current_build_out"
|
||||
current_built_closure=$(sed -n 's/^closure_path=//p' "$current_build_out" | tail -n 1)
|
||||
[ -n "$current_built_closure" ] || { echo "missing closure_path from in-system build output" >&2; exit 1; }
|
||||
case "$current_built_closure" in
|
||||
/frx/store/*-fruix-system-$current_host_name) : ;;
|
||||
*)
|
||||
echo "in-system build of current declaration produced an unexpected closure path: $current_built_closure" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
scp_guest "$candidate_os_file" root@"$guest_ip":/root/candidate.scm >/dev/null
|
||||
ssh_guest "/usr/local/bin/fruix system build /root/candidate.scm --system $system_name" > "$candidate_build_out"
|
||||
candidate_closure=$(sed -n 's/^closure_path=//p' "$candidate_build_out" | tail -n 1)
|
||||
[ -n "$candidate_closure" ] || { echo "missing candidate closure_path from in-system build output" >&2; exit 1; }
|
||||
[ "$candidate_closure" != "$closure_path" ] || {
|
||||
echo "candidate closure unexpectedly matches current closure" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
ssh_guest "/usr/local/bin/fruix system reconfigure /root/candidate.scm --system $system_name" > "$reconfigure_out"
|
||||
reconfigure_closure=$(sed -n 's/^reconfigure_closure=//p' "$reconfigure_out" | tail -n 1)
|
||||
reconfigure_current_generation=$(sed -n 's/^current_generation=//p' "$reconfigure_out" | tail -n 1)
|
||||
reconfigure_current_closure=$(sed -n 's/^current_closure=//p' "$reconfigure_out" | tail -n 1)
|
||||
reconfigure_rollback_generation=$(sed -n 's/^rollback_generation=//p' "$reconfigure_out" | tail -n 1)
|
||||
reconfigure_rollback_closure=$(sed -n 's/^rollback_closure=//p' "$reconfigure_out" | tail -n 1)
|
||||
[ "$reconfigure_closure" = "$candidate_closure" ] || { echo "reconfigure closure mismatch" >&2; exit 1; }
|
||||
[ "$reconfigure_current_generation" = 2 ] || { echo "unexpected current generation after reconfigure: $reconfigure_current_generation" >&2; exit 1; }
|
||||
[ "$reconfigure_current_closure" = "$candidate_closure" ] || { echo "unexpected current closure after reconfigure" >&2; exit 1; }
|
||||
[ "$reconfigure_rollback_generation" = 1 ] || { echo "unexpected rollback generation after reconfigure: $reconfigure_rollback_generation" >&2; exit 1; }
|
||||
[ "$reconfigure_rollback_closure" = "$closure_path" ] || { echo "unexpected rollback closure after reconfigure" >&2; exit 1; }
|
||||
ssh_guest '/usr/local/bin/fruix system status' > "$post_reconfigure_status"
|
||||
|
||||
reboot_guest
|
||||
candidate_hostname=$(ssh_guest 'hostname')
|
||||
candidate_run_current=$(ssh_guest 'readlink /run/current-system')
|
||||
ssh_guest '/usr/local/bin/fruix system status' > "$post_boot_candidate_status"
|
||||
[ "$candidate_hostname" = "$candidate_host_name" ] || { echo "unexpected host name after candidate boot: $candidate_hostname" >&2; exit 1; }
|
||||
[ "$candidate_run_current" = "$candidate_closure" ] || { echo "unexpected current closure after candidate boot: $candidate_run_current" >&2; exit 1; }
|
||||
|
||||
ssh_guest '/usr/local/bin/fruix system rollback' > "$rollback_out"
|
||||
rollback_current_generation=$(sed -n 's/^current_generation=//p' "$rollback_out" | tail -n 1)
|
||||
rollback_current_closure=$(sed -n 's/^current_closure=//p' "$rollback_out" | tail -n 1)
|
||||
rollback_rollback_generation=$(sed -n 's/^rollback_generation=//p' "$rollback_out" | tail -n 1)
|
||||
rollback_rollback_closure=$(sed -n 's/^rollback_closure=//p' "$rollback_out" | tail -n 1)
|
||||
[ "$rollback_current_generation" = 1 ] || { echo "unexpected current generation after rollback: $rollback_current_generation" >&2; exit 1; }
|
||||
[ "$rollback_current_closure" = "$closure_path" ] || { echo "unexpected current closure after rollback" >&2; exit 1; }
|
||||
[ "$rollback_rollback_generation" = 2 ] || { echo "unexpected rollback generation after rollback: $rollback_rollback_generation" >&2; exit 1; }
|
||||
[ "$rollback_rollback_closure" = "$candidate_closure" ] || { echo "unexpected rollback closure after rollback" >&2; exit 1; }
|
||||
|
||||
reboot_guest
|
||||
rollback_hostname=$(ssh_guest 'hostname')
|
||||
rollback_run_current=$(ssh_guest 'readlink /run/current-system')
|
||||
ssh_guest '/usr/local/bin/fruix system status' > "$post_boot_rollback_status"
|
||||
[ "$rollback_hostname" = "$current_host_name" ] || { echo "unexpected host name after rollback boot: $rollback_hostname" >&2; exit 1; }
|
||||
[ "$rollback_run_current" = "$closure_path" ] || { echo "unexpected current closure after rollback boot: $rollback_run_current" >&2; exit 1; }
|
||||
|
||||
cat > "$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
inner_metadata=$inner_metadata
|
||||
phase8_metadata=$phase8_metadata
|
||||
closure_path=$closure_path
|
||||
closure_base=$closure_base
|
||||
vm_id=$vm_id
|
||||
vdi_id=$vdi_id
|
||||
guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
result_store=$result_store
|
||||
current_host_name=$current_host_name
|
||||
candidate_host_name=$candidate_host_name
|
||||
current_build_out=$current_build_out
|
||||
current_built_closure=$current_built_closure
|
||||
candidate_build_out=$candidate_build_out
|
||||
candidate_closure=$candidate_closure
|
||||
reconfigure_out=$reconfigure_out
|
||||
reconfigure_closure=$reconfigure_closure
|
||||
reconfigure_current_generation=$reconfigure_current_generation
|
||||
reconfigure_current_closure=$reconfigure_current_closure
|
||||
reconfigure_rollback_generation=$reconfigure_rollback_generation
|
||||
reconfigure_rollback_closure=$reconfigure_rollback_closure
|
||||
candidate_hostname=$candidate_hostname
|
||||
candidate_run_current=$candidate_run_current
|
||||
rollback_out=$rollback_out
|
||||
rollback_current_generation=$rollback_current_generation
|
||||
rollback_current_closure=$rollback_current_closure
|
||||
rollback_rollback_generation=$rollback_rollback_generation
|
||||
rollback_rollback_closure=$rollback_rollback_closure
|
||||
rollback_hostname=$rollback_hostname
|
||||
rollback_run_current=$rollback_run_current
|
||||
boot_backend=xcp-ng-xo-cli
|
||||
init_mode=shepherd-pid1
|
||||
installed_node_build_reconfigure=ok
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS postphase20-installed-node-build-reconfigure-xcpng\n'
|
||||
printf 'Work directory: %s\n' "$workdir"
|
||||
printf 'Metadata file: %s\n' "$metadata_file"
|
||||
if [ -n "$metadata_target" ]; then
|
||||
printf 'Copied metadata to: %s\n' "$metadata_target"
|
||||
fi
|
||||
printf '%s\n' '--- metadata ---'
|
||||
cat "$metadata_file"
|
||||
Reference in New Issue
Block a user