# 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 per-UUID under /var/cache/. Optional fstab writing, 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](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>](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](src/partition/plan.rs:1) - [fn apply_partitions(plan: &PartitionPlan) -> Result>](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](src/fs/plan.rs:1) - [fn make_filesystems(plan: &FsPlan) -> Result>](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](src/mount/ops.rs:1) - [fn apply_mounts(plan: &MountPlan) -> Result>](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>](src/idempotency/mod.rs:1) - [fn is_empty_disk(disk: &Disk) -> Result](src/idempotency/mod.rs:1) Errors and Result - [enum Error](src/errors.rs:1) - [type Result = std::result::Result](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 - Mount under /var/cache/ using filesystem UUID to create stable subdirectories - Optional /etc/fstab generation disabled by default; when enabled, produce deterministic order with documentation 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