Files
zosstorage/docs/ARCHITECTURE.md

250 lines
11 KiB
Markdown

# zosstorage Architecture
This document defines the repository layout, module boundaries, public API surface (signatures only), defaults, and high-level execution flow for the initramfs-only provisioning utility.
Baseline decisions and labels
- External tools inside initramfs are allowed and will be wrapped via helpers: sgdisk, blkid, mkfs.vfat, mkfs.btrfs, mkfs.bcachefs, udevadm.
- Kernel cmdline key: zosstorage.config=
- Default config path: /etc/zosstorage/config.yaml
- JSON state report path: /run/zosstorage/state.json
- Optional log file path: /run/zosstorage/zosstorage.log
- fstab generation: disabled by default
- GPT partition names: zosboot, zosdata, zoscache
- Filesystem labels:
- ESP: ZOSBOOT
- Data filesystems including bcachefs: ZOSDATA
Repository layout
Top level
- [Cargo.toml](Cargo.toml)
- [PROMPT.md](PROMPT.md)
- [README.md](README.md)
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
- [docs/SCHEMA.md](docs/SCHEMA.md)
- [examples/config/minimal.yaml](examples/config/minimal.yaml)
- [examples/config/dual-btrfs.yaml](examples/config/dual-btrfs.yaml)
- [examples/config/ssd-hdd-bcachefs.yaml](examples/config/ssd-hdd-bcachefs.yaml)
- [tests/](tests/)
- [tests/integration_single_disk.rs](tests/integration_single_disk.rs)
- [tests/integration_dual_disk.rs](tests/integration_dual_disk.rs)
- [tests/integration_ssd_hdd.rs](tests/integration_ssd_hdd.rs)
Crate sources
- [src/main.rs](../src/main.rs)
- [src/lib.rs](../src/lib.rs)
- [src/errors.rs](../src/errors.rs)
- [src/cli/args.rs](../src/cli/args.rs)
- [src/logging/mod.rs](../src/logging/mod.rs)
- [src/config/loader.rs](../src/config/loader.rs)
- [src/types.rs](../src/types.rs)
- [src/device/discovery.rs](../src/device/discovery.rs)
- [src/partition/plan.rs](../src/partition/plan.rs)
- [src/fs/plan.rs](../src/fs/plan.rs)
- [src/mount/ops.rs](../src/mount/ops.rs)
- [src/report/state.rs](../src/report/state.rs)
- [src/orchestrator/run.rs](../src/orchestrator/run.rs)
- [src/idempotency/mod.rs](../src/idempotency/mod.rs)
- [src/util/mod.rs](../src/util/mod.rs)
Module responsibilities
- [src/main.rs](../src/main.rs)
- Entrypoint. Parse CLI, initialize logging, load and merge configuration per precedence, call orchestrator. No stdout spam.
- [src/lib.rs](../src/lib.rs)
- Crate exports, prelude, version constants, Result alias.
- [src/errors.rs](../src/errors.rs)
- Common error enum and Result alias via thiserror.
- [src/cli/args.rs](../src/cli/args.rs)
- CLI definition mirroring kernel cmdline semantics; provide non-interactive interface. Stub --force returns unimplemented.
- [src/logging/mod.rs](../src/logging/mod.rs)
- Initialize tracing; levels error, warn, info, debug; default to stderr; optional file target.
- [src/config/loader.rs](../src/config/loader.rs) and [src/types.rs](../src/types.rs)
- YAML schema types, validation, loading, and merging with CLI and kernel cmdline.
- [src/device/discovery.rs](../src/device/discovery.rs)
- Device discovery under /dev with filters and allowlist; probe emptiness safely.
- [src/partition/plan.rs](../src/partition/plan.rs)
- GPT-only planning and application; 1 MiB alignment; create bios boot, ESP, data and cache partitions with strict safety checks.
- [src/fs/plan.rs](../src/fs/plan.rs)
- Filesystem provisioning: vfat for ESP, btrfs for ZOSDATA, bcachefs for SSD+HDD mode; all data filesystems labeled ZOSDATA.
- [src/mount/ops.rs](../src/mount/ops.rs)
- Mount scheme:
- Root-mount all data filesystems under `/var/mounts/{UUID}` (runtime only)
- btrfs root: `rw,noatime,subvolid=5`
- bcachefs root: `rw,noatime`
- Create or ensure subvolumes on the primary data filesystem: `system`, `etc`, `modules`, `vm-meta`
- Mount final subvolume/subdir targets at `/var/cache/{system,etc,modules,vm-meta}`
- Optional fstab writing: only the four final targets, deterministic order, `UUID=` sources; disabled by default
- [src/report/state.rs](../src/report/state.rs)
- Build and write JSON state report with version field.
- [src/orchestrator/run.rs](../src/orchestrator/run.rs)
- One-shot flow orchestration with abort-on-any-validation-error policy.
- [src/idempotency/mod.rs](../src/idempotency/mod.rs)
- Detect prior provisioning via GPT names and labels; return success-without-changes.
- [src/util/mod.rs](../src/util/mod.rs)
- Shell-out, udev settle, and helpers.
Public API surface (signatures; implementation to follow after approval)
Entrypoint and orchestrator
- [fn main()](../src/main.rs:1)
- [struct Context](../src/orchestrator/run.rs:1)
- [fn run(ctx: &Context) -> Result<()>](../src/orchestrator/run.rs:1)
CLI
- [struct Cli](../src/cli/args.rs:1)
- [fn from_args() -> Cli](../src/cli/args.rs:1)
Logging
- [struct LogOptions](../src/logging/mod.rs:1)
- [fn init_logging(opts: &LogOptions) -> Result<()>](../src/logging/mod.rs:1)
Config
- [struct Config](../src/types.rs:1)
- [enum Topology](../src/types.rs:1)
- [struct DeviceSelection](../src/types.rs:1)
- [struct FsOptions](../src/types.rs:1)
- [struct MountScheme](../src/types.rs:1)
- [fn load_and_merge(cli: &Cli) -> Result<Config>](../src/config/loader.rs:1)
- [fn validate(cfg: &Config) -> Result<()>](../src/config/loader.rs:1)
Device discovery
- [struct Disk](../src/device/discovery.rs:1)
- [struct DeviceFilter](../src/device/discovery.rs:1)
- [trait DeviceProvider](../src/device/discovery.rs:1)
- [fn discover(filter: &DeviceFilter) -> Result<Vec<Disk>>](../src/device/discovery.rs:1)
Partitioning
- [struct PartitionSpec](../src/partition/plan.rs:1)
- [struct PartitionPlan](../src/partition/plan.rs:1)
- [struct PartitionResult](../src/partition/plan.rs:1)
- [fn plan_partitions(disks: &[Disk], cfg: &Config) -> Result<PartitionPlan>](../src/partition/plan.rs:1)
- [fn apply_partitions(plan: &PartitionPlan) -> Result<Vec<PartitionResult>>](../src/partition/plan.rs:1)
Filesystems
- [enum FsKind](../src/fs/plan.rs:1)
- [struct FsSpec](../src/fs/plan.rs:1)
- [struct FsPlan](../src/fs/plan.rs:1)
- [struct FsResult](../src/fs/plan.rs:1)
- [fn plan_filesystems(disks: &[Disk], parts: &[PartitionResult], cfg: &Config) -> Result<FsPlan>](../src/fs/plan.rs:1)
- [fn make_filesystems(plan: &FsPlan) -> Result<Vec<FsResult>>](../src/fs/plan.rs:1)
Mounting
- [struct MountPlan](../src/mount/ops.rs:1)
- [struct MountResult](../src/mount/ops.rs:1)
- [fn plan_mounts(fs_results: &[FsResult], cfg: &Config) -> Result<MountPlan>](../src/mount/ops.rs:1)
- [fn apply_mounts(plan: &MountPlan) -> Result<Vec<MountResult>>](../src/mount/ops.rs:1)
- [fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config) -> Result<()>](../src/mount/ops.rs:1)
Reporting
- [const REPORT_VERSION: &str](../src/report/state.rs:1)
- [struct StateReport](../src/report/state.rs:1)
- [fn build_report(...) -> StateReport](../src/report/state.rs:1)
- [fn write_report(report: &StateReport) -> Result<()>](../src/report/state.rs:1)
Idempotency
- [fn detect_existing_state() -> Result<Option<StateReport>>](../src/idempotency/mod.rs:1)
- [fn is_empty_disk(disk: &Disk) -> Result<bool>](../src/idempotency/mod.rs:1)
Errors and Result
- [enum Error](../src/errors.rs:1)
- [type Result<T> = std::result::Result<T, Error>](../src/errors.rs:1)
Execution flow
```mermaid
flowchart TD
A[Start] --> B[Initialize logging]
B --> C[Parse CLI and kernel cmdline]
C --> D[Load and validate config]
D --> E[Idempotency detection]
E -->|already provisioned| Z[Exit success]
E -->|not provisioned| F[Discover devices]
F --> G[Plan partitions]
G --> H[Apply partitions]
H --> I[Plan filesystems]
I --> J[Create filesystems]
J --> K[Plan mounts]
K --> L[Apply mounts]
L --> M[Write state report]
M --> N[Finalize]
N --> Z[Exit success]
```
Configuration precedence
- Kernel cmdline key zosstorage.config= overrides CLI and file
- CLI flags override config file
- Config file provides defaults at /etc/zosstorage/config.yaml
- No interactive prompts in initramfs
Device discovery and filtering
- Include device classes by default: /dev/sd*, /dev/nvme*, /dev/vd*
- Exclude pseudodevices: /dev/ram*, /dev/zram*, /dev/fd*, /dev/loop*, etc.
- Allow future allowlists and removable media policies via configuration
- If no eligible disks are found, return a well-defined error
Partitioning plan
- GPT exclusively with 1 MiB alignment
- bios boot partition first, 1 MiB
- ESP 512 MiB FAT32, label ZOSBOOT, GPT name zosboot
- Data partition consumes remainder, GPT name zosdata
- When cache is requested, create GPT name zoscache partitions as needed
- Abort if any pre-existing partitions or filesystem signatures are detected
- Ensure unique partition UUIDs and identical labels where required
Filesystem provisioning defaults
- Single disk: btrfs labeled ZOSDATA
- Two disks: btrfs per disk labeled ZOSDATA, no RAID by default
- SSD plus HDD: bcachefs with SSD as cache or promote and HDD as backing, filesystem label ZOSDATA
- Filesystem tuning options configurable with sensible defaults and extension points
Mount scheme and fstab policy
- Runtime root mounts:
- Each data filesystem is root-mounted at `/var/mounts/{UUID}` (runtime only)
- btrfs: `rw,noatime,subvolid=5`; bcachefs: `rw,noatime`
- Final targets (from primary data filesystem only):
- `/var/cache/system`, `/var/cache/etc`, `/var/cache/modules`, `/var/cache/vm-meta`
- btrfs subvolume option: `-o subvol={name},noatime`
- bcachefs subdir option: `-o X-mount.subdir={name},noatime`
- /etc/fstab generation:
- Disabled by default. When enabled, write only the four final targets with `UUID=` sources in deterministic order. Root mounts under `/var/mounts` are excluded.
Idempotency detection
- Consider the system provisioned when expected GPT names and filesystem labels are present and consistent
- On a provisioned system, exit success without making any changes
Reporting
- Emit machine-readable JSON state report at /run/zosstorage/state.json
- Report includes enumerated disks and roles, created partitions with identifiers, filesystems with labels and mountpoints, overall status and timestamp
- Version the report payload via REPORT_VERSION
Logging
- Use tracing with levels error, warn, info, debug
- Default to stderr; optionally log to file at /run/zosstorage/zosstorage.log
- Avoid println and stdout spam
External tooling policy
- Invoke system utilities via wrappers that check for tool availability, capture stderr, and emit structured logs
- Provide udev settle helper; avoid reliance on long-running services
Planned dependencies to add via cargo add
- clap
- serde, serde_yaml, serde_json
- thiserror
- anyhow or eyre
- tracing, tracing-subscriber
- nix
- regex
- uuid
- which
- time
- tempfile
Open items and assumptions to track
- Exact BIOS boot size and placement pending confirmation; currently 1 MiB first
- Final mount naming scheme under /var/cache may evolve
- Filesystem tuning defaults for btrfs and bcachefs require stakeholder input
- Paths for config, report, and log file may be adjusted later
- fstab generation remains disabled by default pending decision
Next steps after approval
- Formalize configuration schema and validation rules in [docs/SCHEMA.md](docs/SCHEMA.md)
- Define detailed doc comments for all listed types and functions
- Prepare code-mode implementation skeletons with todo placeholders and add dependencies via cargo add