250 lines
11 KiB
Markdown
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 |