docs: sync with code (topologies, mount scheme, CLI flags, UEFI/BIOS, fstab) and fix relative src links in docs/ to ../src/
This commit is contained in:
@@ -6,34 +6,34 @@ Purpose
|
||||
- After approval, these will be created in the src tree in Code mode.
|
||||
|
||||
Index
|
||||
- [src/lib.rs](src/lib.rs)
|
||||
- [src/errors.rs](src/errors.rs)
|
||||
- [src/main.rs](src/main.rs)
|
||||
- [src/cli/args.rs](src/cli/args.rs)
|
||||
- [src/logging/mod.rs](src/logging/mod.rs)
|
||||
- [src/types.rs](src/types.rs)
|
||||
- [src/config/loader.rs](src/config/loader.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)
|
||||
- [src/lib.rs](../src/lib.rs)
|
||||
- [src/errors.rs](../src/errors.rs)
|
||||
- [src/main.rs](../src/main.rs)
|
||||
- [src/cli/args.rs](../src/cli/args.rs)
|
||||
- [src/logging/mod.rs](../src/logging/mod.rs)
|
||||
- [src/types.rs](../src/types.rs)
|
||||
- [src/config/loader.rs](../src/config/loader.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)
|
||||
|
||||
Conventions
|
||||
- Shared [type Result<T>](src/errors.rs:1) and [enum Error](src/errors.rs:1).
|
||||
- Shared [type Result<T>](../src/errors.rs:1) and [enum Error](../src/errors.rs:1).
|
||||
- No stdout prints; use tracing only.
|
||||
- External tools invoked via [util](src/util/mod.rs) wrappers.
|
||||
- External tools invoked via [util](../src/util/mod.rs) wrappers.
|
||||
|
||||
---
|
||||
|
||||
## Crate root
|
||||
|
||||
References
|
||||
- [src/lib.rs](src/lib.rs)
|
||||
- [type Result<T> = std::result::Result<T, Error>](src/errors.rs:1)
|
||||
- [src/lib.rs](../src/lib.rs)
|
||||
- [type Result<T> = std::result::Result<T, Error>](../src/errors.rs:1)
|
||||
|
||||
Skeleton (for later implementation in code mode)
|
||||
```rust
|
||||
@@ -63,8 +63,8 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
## Errors
|
||||
|
||||
References
|
||||
- [enum Error](src/errors.rs:1)
|
||||
- [type Result<T>](src/errors.rs:1)
|
||||
- [enum Error](../src/errors.rs:1)
|
||||
- [type Result<T>](../src/errors.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -107,8 +107,8 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
## Entrypoint
|
||||
|
||||
References
|
||||
- [fn main()](src/main.rs:1)
|
||||
- [fn run(ctx: &Context) -> Result<()>](src/orchestrator/run.rs:1)
|
||||
- [fn main()](../src/main.rs:1)
|
||||
- [fn run(ctx: &Context) -> Result<()>](../src/orchestrator/run.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -143,8 +143,8 @@ fn real_main() -> Result<()> {
|
||||
## CLI
|
||||
|
||||
References
|
||||
- [struct Cli](src/cli/args.rs:1)
|
||||
- [fn from_args() -> Cli](src/cli/args.rs:1)
|
||||
- [struct Cli](../src/cli/args.rs:1)
|
||||
- [fn from_args() -> Cli](../src/cli/args.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -170,6 +170,18 @@ pub struct Cli {
|
||||
#[arg(long = "fstab", default_value_t = false)]
|
||||
pub fstab: bool,
|
||||
|
||||
/// Print preview JSON to stdout (non-destructive)
|
||||
#[arg(long = "show", default_value_t = false)]
|
||||
pub show: bool,
|
||||
|
||||
/// Write preview JSON to a file (non-destructive)
|
||||
#[arg(long = "report")]
|
||||
pub report: Option<String>,
|
||||
|
||||
/// Perform partitioning, filesystem creation, and mounts (DESTRUCTIVE)
|
||||
#[arg(long = "apply", default_value_t = false)]
|
||||
pub apply: bool,
|
||||
|
||||
/// Present but non-functional; returns unimplemented error
|
||||
#[arg(long = "force")]
|
||||
pub force: bool,
|
||||
@@ -186,8 +198,8 @@ pub fn from_args() -> Cli {
|
||||
## Logging
|
||||
|
||||
References
|
||||
- [struct LogOptions](src/logging/mod.rs:1)
|
||||
- [fn init_logging(opts: &LogOptions) -> Result<()>](src/logging/mod.rs:1)
|
||||
- [struct LogOptions](../src/logging/mod.rs:1)
|
||||
- [fn init_logging(opts: &LogOptions) -> Result<()>](../src/logging/mod.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -218,13 +230,13 @@ pub fn init_logging(opts: &LogOptions) -> Result<()> {
|
||||
## Configuration types
|
||||
|
||||
References
|
||||
- [struct Config](src/types.rs:1)
|
||||
- [enum Topology](src/types.rs:1)
|
||||
- [struct DeviceSelection](src/types.rs:1)
|
||||
- [struct Partitioning](src/types.rs:1)
|
||||
- [struct FsOptions](src/types.rs:1)
|
||||
- [struct MountScheme](src/types.rs:1)
|
||||
- [struct ReportOptions](src/types.rs:1)
|
||||
- [struct Config](../src/types.rs:1)
|
||||
- [enum Topology](../src/types.rs:1)
|
||||
- [struct DeviceSelection](../src/types.rs:1)
|
||||
- [struct Partitioning](../src/types.rs:1)
|
||||
- [struct FsOptions](../src/types.rs:1)
|
||||
- [struct MountScheme](../src/types.rs:1)
|
||||
- [struct ReportOptions](../src/types.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -247,8 +259,10 @@ pub struct DeviceSelection {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Topology {
|
||||
Single,
|
||||
BtrfsSingle,
|
||||
BcachefsSingle,
|
||||
DualIndependent,
|
||||
Bcachefs2Copy,
|
||||
SsdHddBcachefs,
|
||||
BtrfsRaid1,
|
||||
}
|
||||
@@ -351,8 +365,8 @@ pub struct Config {
|
||||
## Configuration I/O
|
||||
|
||||
References
|
||||
- [fn load_and_merge(cli: &Cli) -> Result<Config>](src/config/loader.rs:1)
|
||||
- [fn validate(cfg: &Config) -> Result<()>](src/config/loader.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)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -374,10 +388,10 @@ pub fn validate(cfg: &crate::config::types::Config) -> Result<()> {
|
||||
## Device discovery
|
||||
|
||||
References
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -418,12 +432,12 @@ pub fn discover(filter: &DeviceFilter) -> Result<Vec<Disk>> {
|
||||
## Partitioning
|
||||
|
||||
References
|
||||
- [enum PartRole](src/partition/plan.rs:1)
|
||||
- [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)
|
||||
- [enum PartRole](../src/partition/plan.rs:1)
|
||||
- [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)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -485,12 +499,12 @@ pub fn apply_partitions(plan: &PartitionPlan) -> Result<Vec<PartitionResult>> {
|
||||
## Filesystems
|
||||
|
||||
References
|
||||
- [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(...)](src/fs/plan.rs:1)
|
||||
- [fn make_filesystems(...)](src/fs/plan.rs:1)
|
||||
- [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(...)](../src/fs/plan.rs:1)
|
||||
- [fn make_filesystems(...)](../src/fs/plan.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -531,8 +545,8 @@ pub fn plan_filesystems(
|
||||
todo!("map ESP to vfat, data to btrfs or bcachefs according to topology")
|
||||
}
|
||||
|
||||
/// Create the filesystems and return identity info (UUIDs, labels).
|
||||
pub fn make_filesystems(plan: &FsPlan) -> Result<Vec<FsResult>> {
|
||||
//// Create the filesystems and return identity info (UUIDs, labels).
|
||||
pub fn make_filesystems(plan: &FsPlan, cfg: &Config) -> Result<Vec<FsResult>> {
|
||||
todo!("invoke mkfs tools with configured options via util::run_cmd")
|
||||
}
|
||||
```
|
||||
@@ -542,11 +556,11 @@ pub fn make_filesystems(plan: &FsPlan) -> Result<Vec<FsResult>> {
|
||||
## Mounting
|
||||
|
||||
References
|
||||
- [struct MountPlan](src/mount/ops.rs:1)
|
||||
- [struct MountResult](src/mount/ops.rs:1)
|
||||
- [fn plan_mounts(...)](src/mount/ops.rs:1)
|
||||
- [fn apply_mounts(...)](src/mount/ops.rs:1)
|
||||
- [fn maybe_write_fstab(...)](src/mount/ops.rs:1)
|
||||
- [struct MountPlan](../src/mount/ops.rs:1)
|
||||
- [struct MountResult](../src/mount/ops.rs:1)
|
||||
- [fn plan_mounts(...)](../src/mount/ops.rs:1)
|
||||
- [fn apply_mounts(...)](../src/mount/ops.rs:1)
|
||||
- [fn maybe_write_fstab(...)](../src/mount/ops.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -565,9 +579,13 @@ pub struct MountResult {
|
||||
pub options: String,
|
||||
}
|
||||
|
||||
/// Build mount plan under /var/cache/<UUID> by default.
|
||||
//// Build mount plan:
|
||||
//// - Root-mount all data filesystems under `/var/mounts/{UUID}` (runtime only)
|
||||
//// - Ensure/create subvolumes on the primary data filesystem: system, etc, modules, vm-meta
|
||||
//// - Plan final mounts to `/var/cache/{system,etc,modules,vm-meta}` using
|
||||
//// `subvol=` for btrfs and `X-mount.subdir=` for bcachefs.
|
||||
pub fn plan_mounts(fs_results: &[FsResult], cfg: &Config) -> Result<MountPlan> {
|
||||
todo!("create per-UUID directories and mount mapping")
|
||||
todo!("root mounts under /var/mounts/{UUID}; final subvol/subdir mounts to /var/cache/{system,etc,modules,vm-meta}")
|
||||
}
|
||||
|
||||
/// Apply mounts using syscalls (nix), ensuring directories exist.
|
||||
@@ -575,9 +593,12 @@ pub fn apply_mounts(plan: &MountPlan) -> Result<Vec<MountResult>> {
|
||||
todo!("perform mount syscalls and return results")
|
||||
}
|
||||
|
||||
/// Optionally generate /etc/fstab entries in deterministic order.
|
||||
//// Optionally generate /etc/fstab entries for final subvolume/subdir mounts only.
|
||||
//// - Write exactly four entries: system, etc, modules, vm-meta
|
||||
//// - Use UUID= sources; deterministic order by target path
|
||||
//// - Exclude runtime root mounts under `/var/mounts/{UUID}`
|
||||
pub fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config) -> Result<()> {
|
||||
todo!("when enabled, write fstab entries")
|
||||
todo!("when enabled, write only the four final subvolume/subdir entries with UUID= sources")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -586,10 +607,10 @@ pub fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config) -> Result<()> {
|
||||
## Reporting
|
||||
|
||||
References
|
||||
- [const REPORT_VERSION: &str](src/report/state.rs:1)
|
||||
- [struct StateReport](src/report/state.rs:1)
|
||||
- [fn build_report(...)](src/report/state.rs:1)
|
||||
- [fn write_report(...)](src/report/state.rs:1)
|
||||
- [const REPORT_VERSION: &str](../src/report/state.rs:1)
|
||||
- [struct StateReport](../src/report/state.rs:1)
|
||||
- [fn build_report(...)](../src/report/state.rs:1)
|
||||
- [fn write_report(...)](../src/report/state.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -632,8 +653,8 @@ pub fn write_report(report: &StateReport, path: &str) -> Result<()> {
|
||||
## Orchestrator
|
||||
|
||||
References
|
||||
- [struct Context](src/orchestrator/run.rs:1)
|
||||
- [fn run(ctx: &Context) -> Result<()>](src/orchestrator/run.rs:1)
|
||||
- [struct Context](../src/orchestrator/run.rs:1)
|
||||
- [fn run(ctx: &Context) -> Result<()>](../src/orchestrator/run.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -662,8 +683,8 @@ pub fn run(ctx: &Context) -> Result<()> {
|
||||
## Idempotency
|
||||
|
||||
References
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -685,11 +706,11 @@ pub fn is_empty_disk(disk: &Disk) -> Result<bool> {
|
||||
## Utilities
|
||||
|
||||
References
|
||||
- [struct CmdOutput](src/util/mod.rs:1)
|
||||
- [fn which_tool(name: &str) -> Result<Option<String>>](src/util/mod.rs:1)
|
||||
- [fn run_cmd(args: &[&str]) -> Result<()>](src/util/mod.rs:1)
|
||||
- [fn run_cmd_capture(args: &[&str]) -> Result<CmdOutput>](src/util/mod.rs:1)
|
||||
- [fn udev_settle(timeout_ms: u64) -> Result<()>](src/util/mod.rs:1)
|
||||
- [struct CmdOutput](../src/util/mod.rs:1)
|
||||
- [fn which_tool(name: &str) -> Result<Option<String>>](../src/util/mod.rs:1)
|
||||
- [fn run_cmd(args: &[&str]) -> Result<()>](../src/util/mod.rs:1)
|
||||
- [fn run_cmd_capture(args: &[&str]) -> Result<CmdOutput>](../src/util/mod.rs:1)
|
||||
- [fn udev_settle(timeout_ms: u64) -> Result<()>](../src/util/mod.rs:1)
|
||||
|
||||
Skeleton
|
||||
```rust
|
||||
@@ -722,6 +743,11 @@ pub fn run_cmd_capture(args: &[&str]) -> Result<CmdOutput> {
|
||||
pub fn udev_settle(timeout_ms: u64) -> Result<()> {
|
||||
todo!("invoke udevadm settle when present")
|
||||
}
|
||||
|
||||
/// Detect UEFI environment by checking /sys/firmware/efi; used to suppress BIOS boot partition on UEFI.
|
||||
pub fn is_efi_boot() -> bool {
|
||||
todo!("return Path::new(\"/sys/firmware/efi\").exists()")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
@@ -735,24 +761,24 @@ Approval gate
|
||||
- Add initial tests scaffolding and example configs.
|
||||
|
||||
References summary
|
||||
- [fn main()](src/main.rs:1)
|
||||
- [fn from_args()](src/cli/args.rs:1)
|
||||
- [fn init_logging(opts: &LogOptions)](src/logging/mod.rs:1)
|
||||
- [fn load_and_merge(cli: &Cli)](src/config/loader.rs:1)
|
||||
- [fn validate(cfg: &Config)](src/config/loader.rs:1)
|
||||
- [fn discover(filter: &DeviceFilter)](src/device/discovery.rs:1)
|
||||
- [fn plan_partitions(disks: &[Disk], cfg: &Config)](src/partition/plan.rs:1)
|
||||
- [fn apply_partitions(plan: &PartitionPlan)](src/partition/plan.rs:1)
|
||||
- [fn plan_filesystems(parts: &[PartitionResult], cfg: &Config)](src/fs/plan.rs:1)
|
||||
- [fn make_filesystems(plan: &FsPlan)](src/fs/plan.rs:1)
|
||||
- [fn plan_mounts(fs_results: &[FsResult], cfg: &Config)](src/mount/ops.rs:1)
|
||||
- [fn apply_mounts(plan: &MountPlan)](src/mount/ops.rs:1)
|
||||
- [fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config)](src/mount/ops.rs:1)
|
||||
- [fn build_report(...)](src/report/state.rs:1)
|
||||
- [fn write_report(report: &StateReport)](src/report/state.rs:1)
|
||||
- [fn detect_existing_state()](src/idempotency/mod.rs:1)
|
||||
- [fn is_empty_disk(disk: &Disk)](src/idempotency/mod.rs:1)
|
||||
- [fn which_tool(name: &str)](src/util/mod.rs:1)
|
||||
- [fn run_cmd(args: &[&str])](src/util/mod.rs:1)
|
||||
- [fn run_cmd_capture(args: &[&str])](src/util/mod.rs:1)
|
||||
- [fn udev_settle(timeout_ms: u64)](src/util/mod.rs:1)
|
||||
- [fn main()](../src/main.rs:1)
|
||||
- [fn from_args()](../src/cli/args.rs:1)
|
||||
- [fn init_logging(opts: &LogOptions)](../src/logging/mod.rs:1)
|
||||
- [fn load_and_merge(cli: &Cli)](../src/config/loader.rs:1)
|
||||
- [fn validate(cfg: &Config)](../src/config/loader.rs:1)
|
||||
- [fn discover(filter: &DeviceFilter)](../src/device/discovery.rs:1)
|
||||
- [fn plan_partitions(disks: &[Disk], cfg: &Config)](../src/partition/plan.rs:1)
|
||||
- [fn apply_partitions(plan: &PartitionPlan)](../src/partition/plan.rs:1)
|
||||
- [fn plan_filesystems(parts: &[PartitionResult], cfg: &Config)](../src/fs/plan.rs:1)
|
||||
- [fn make_filesystems(plan: &FsPlan)](../src/fs/plan.rs:1)
|
||||
- [fn plan_mounts(fs_results: &[FsResult], cfg: &Config)](../src/mount/ops.rs:1)
|
||||
- [fn apply_mounts(plan: &MountPlan)](../src/mount/ops.rs:1)
|
||||
- [fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config)](../src/mount/ops.rs:1)
|
||||
- [fn build_report(...)](../src/report/state.rs:1)
|
||||
- [fn write_report(report: &StateReport)](../src/report/state.rs:1)
|
||||
- [fn detect_existing_state()](../src/idempotency/mod.rs:1)
|
||||
- [fn is_empty_disk(disk: &Disk)](../src/idempotency/mod.rs:1)
|
||||
- [fn which_tool(name: &str)](../src/util/mod.rs:1)
|
||||
- [fn run_cmd(args: &[&str])](../src/util/mod.rs:1)
|
||||
- [fn run_cmd_capture(args: &[&str])](../src/util/mod.rs:1)
|
||||
- [fn udev_settle(timeout_ms: u64)](../src/util/mod.rs:1)
|
||||
169
docs/API.md
169
docs/API.md
@@ -8,40 +8,40 @@ Conventions
|
||||
- External tooling calls are mediated via utility wrappers.
|
||||
|
||||
Module index
|
||||
- [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/types.rs](src/types.rs)
|
||||
- [src/config/loader.rs](src/config/loader.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)
|
||||
- [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/types.rs](../src/types.rs)
|
||||
- [src/config/loader.rs](../src/config/loader.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)
|
||||
|
||||
Common errors and result
|
||||
- [enum Error](src/errors.rs:1)
|
||||
- [enum Error](../src/errors.rs:1)
|
||||
- Top-level error type covering parse/validation errors, device discovery errors, partitioning failures, filesystem mkfs errors, mount errors, report write errors, and external tool invocation failures with stderr capture.
|
||||
- [type Result<T> = std::result::Result<T, Error>](src/errors.rs:1)
|
||||
- [type Result<T> = std::result::Result<T, Error>](../src/errors.rs:1)
|
||||
- Shared result alias across modules.
|
||||
|
||||
Crate root
|
||||
- [src/lib.rs](src/lib.rs)
|
||||
- [src/lib.rs](../src/lib.rs)
|
||||
- Exposes crate version constants, the prelude, and re-exports common types for consumers of the library (tests/integration). No heavy logic.
|
||||
|
||||
Entrypoint
|
||||
- [fn main()](src/main.rs:1)
|
||||
- [fn main()](../src/main.rs:1)
|
||||
- Initializes logging based on CLI defaults, parses CLI flags and kernel cmdline, loads and validates configuration, and invokes the orchestrator run sequence. Avoids stdout; logs via tracing only.
|
||||
|
||||
Orchestrator
|
||||
- [struct Context](src/orchestrator/run.rs:1)
|
||||
- [struct Context](../src/orchestrator/run.rs:1)
|
||||
- Aggregates resolved configuration, logging options, and environment flags suited for initramfs execution.
|
||||
- [fn run(ctx: &Context) -> Result<()>](src/orchestrator/run.rs:1)
|
||||
- [fn run(ctx: &Context) -> Result<()>](../src/orchestrator/run.rs:1)
|
||||
- High-level one-shot flow:
|
||||
- Idempotency detection
|
||||
- Device discovery
|
||||
@@ -52,131 +52,141 @@ Orchestrator
|
||||
- Aborts the entire run on any validation or execution failure. Returns Ok on successful no-op if already provisioned.
|
||||
|
||||
CLI
|
||||
- [struct Cli](src/cli/args.rs:1)
|
||||
- [struct Cli](../src/cli/args.rs:1)
|
||||
- Mirrors kernel cmdline semantics with flags:
|
||||
- --config PATH
|
||||
- --log-level LEVEL
|
||||
- --log-to-file
|
||||
- --fstab
|
||||
- --show
|
||||
- --report PATH
|
||||
- --apply
|
||||
- --force (present, returns unimplemented error)
|
||||
- [fn from_args() -> Cli](src/cli/args.rs:1)
|
||||
- [fn from_args() -> Cli](../src/cli/args.rs:1)
|
||||
- Parses argv without side effects; suitable for initramfs.
|
||||
|
||||
Logging
|
||||
- [struct LogOptions](src/logging/mod.rs:1)
|
||||
- [struct LogOptions](../src/logging/mod.rs:1)
|
||||
- Holds level and optional file target (/run/zosstorage/zosstorage.log).
|
||||
- [fn init_logging(opts: &LogOptions) -> Result<()>](src/logging/mod.rs:1)
|
||||
- [fn init_logging(opts: &LogOptions) -> Result<()>](../src/logging/mod.rs:1)
|
||||
- Configures tracing-subscriber for stderr by default and optional file layer when enabled. Must be idempotent.
|
||||
|
||||
Configuration types
|
||||
- [struct Config](src/types.rs:1)
|
||||
- [struct Config](../src/types.rs:1)
|
||||
- The validated configuration used by the orchestrator, containing logging, device selection rules, topology, partitioning, filesystem options, mount scheme, and report path.
|
||||
- [enum Topology](src/types.rs:1)
|
||||
- Values: btrfs_single, bcachefs_single, dual_independent, bcachefs_2copy, ssd_hdd_bcachefs, btrfs_raid1 (opt-in).
|
||||
- [struct DeviceSelection](src/types.rs:1)
|
||||
- [enum Topology](../src/types.rs:1)
|
||||
- Values: btrfs_single, bcachefs_single, dual_independent, bcachefs2_copy, ssd_hdd_bcachefs, btrfs_raid1 (opt-in).
|
||||
- [struct DeviceSelection](../src/types.rs:1)
|
||||
- Include and exclude regex patterns, minimum size, removable policy.
|
||||
- [struct Partitioning](src/types.rs:1)
|
||||
- [struct Partitioning](../src/types.rs:1)
|
||||
- Alignment, emptiness requirement, bios_boot, esp, data, cache GPT names and sizes where applicable.
|
||||
- [struct BtrfsOptions](src/types.rs:1)
|
||||
- [struct BtrfsOptions](../src/types.rs:1)
|
||||
- Compression string and raid profile (none or raid1).
|
||||
- [struct BcachefsOptions](src/types.rs:1)
|
||||
- [struct BcachefsOptions](../src/types.rs:1)
|
||||
- Cache mode (promote or writeback), compression, checksum.
|
||||
- [struct VfatOptions](src/types.rs:1)
|
||||
- [struct VfatOptions](../src/types.rs:1)
|
||||
- Reserved for ESP mkfs options; includes label ZOSBOOT.
|
||||
- [struct FsOptions](src/types.rs:1)
|
||||
- [struct FsOptions](../src/types.rs:1)
|
||||
- Aggregates BtrfsOptions, BcachefsOptions, VfatOptions and shared defaults such as ZOSDATA label.
|
||||
- [enum MountSchemeKind](src/types.rs:1)
|
||||
- [enum MountSchemeKind](../src/types.rs:1)
|
||||
- Values: per_uuid, custom (future).
|
||||
- [struct MountScheme](src/types.rs:1)
|
||||
- [struct MountScheme](../src/types.rs:1)
|
||||
- Base directory (/var/cache), scheme kind, fstab enabled flag.
|
||||
- [struct ReportOptions](src/types.rs:1)
|
||||
- [struct ReportOptions](../src/types.rs:1)
|
||||
- Output path (/run/zosstorage/state.json).
|
||||
|
||||
Configuration IO
|
||||
- [fn load_and_merge(cli: &Cli) -> Result<Config>](src/config/loader.rs:1)
|
||||
- [fn load_and_merge(cli: &Cli) -> Result<Config>](../src/config/loader.rs:1)
|
||||
- Loads built-in defaults, optionally merges on-disk config, overlays CLI flags, and finally overlays kernel cmdline via zosstorage.config=. Validates the YAML against types and constraints.
|
||||
- [fn validate(cfg: &Config) -> Result<()>](src/config/loader.rs:1)
|
||||
- [fn validate(cfg: &Config) -> Result<()>](../src/config/loader.rs:1)
|
||||
- Ensures structural and semantic validity (e.g., disk selection rules not empty, sizes non-zero, supported topology combinations).
|
||||
|
||||
Device discovery
|
||||
- [struct Disk](src/device/discovery.rs:1)
|
||||
- [struct Disk](../src/device/discovery.rs:1)
|
||||
- Represents an eligible block device with path, size, rotational flag, and identifiers (serial, model if available).
|
||||
- [struct DeviceFilter](src/device/discovery.rs:1)
|
||||
- [struct DeviceFilter](../src/device/discovery.rs:1)
|
||||
- Derived from DeviceSelection; compiled regexes and size thresholds for efficient filtering.
|
||||
- [trait DeviceProvider](src/device/discovery.rs:1)
|
||||
- [trait DeviceProvider](../src/device/discovery.rs:1)
|
||||
- Abstraction for listing /dev and probing properties, enabling test doubles.
|
||||
- [fn discover(filter: &DeviceFilter) -> Result<Vec<Disk>>](src/device/discovery.rs:1)
|
||||
- [fn discover(filter: &DeviceFilter) -> Result<Vec<Disk>>](../src/device/discovery.rs:1)
|
||||
- Returns eligible disks or a well-defined error if none are found.
|
||||
|
||||
Partitioning
|
||||
- [enum PartRole](src/partition/plan.rs:1)
|
||||
- [enum PartRole](../src/partition/plan.rs:1)
|
||||
- Roles: BiosBoot, Esp, Data, Cache.
|
||||
- [struct PartitionSpec](src/partition/plan.rs:1)
|
||||
- [struct PartitionSpec](../src/partition/plan.rs:1)
|
||||
- Declarative spec for a single partition: role, optional size_mib, gpt_name (zosboot, zosdata, zoscache), and reserved filesystem label when role is Esp (ZOSBOOT).
|
||||
- [struct DiskPlan](src/partition/plan.rs:1)
|
||||
- [struct DiskPlan](../src/partition/plan.rs:1)
|
||||
- The planned set of PartitionSpec instances for a single Disk in the chosen topology.
|
||||
- [struct PartitionPlan](src/partition/plan.rs:1)
|
||||
- [struct PartitionPlan](../src/partition/plan.rs:1)
|
||||
- Combined plan across all target disks, including alignment rules and safety checks.
|
||||
- [struct PartitionResult](src/partition/plan.rs:1)
|
||||
- [struct PartitionResult](../src/partition/plan.rs:1)
|
||||
- Result of applying a DiskPlan: device path of each created partition, role, partition GUID, and gpt_name.
|
||||
- [fn plan_partitions(disks: &[Disk], cfg: &Config) -> Result<PartitionPlan>](src/partition/plan.rs:1)
|
||||
- [fn plan_partitions(disks: &[Disk], cfg: &Config) -> Result<PartitionPlan>](../src/partition/plan.rs:1)
|
||||
- Produces a GPT-only plan with 1 MiB alignment, bios boot first (1 MiB), ESP 512 MiB, data remainder, and zoscache on SSD for ssd_hdd_bcachefs.
|
||||
- [fn apply_partitions(plan: &PartitionPlan) -> Result<Vec<PartitionResult>>](src/partition/plan.rs:1)
|
||||
- [fn apply_partitions(plan: &PartitionPlan) -> Result<Vec<PartitionResult>>](../src/partition/plan.rs:1)
|
||||
- Executes the plan via sgdisk and related utilities. Aborts if target disks are not empty or if signatures are detected.
|
||||
|
||||
Filesystems
|
||||
- [enum FsKind](src/fs/plan.rs:1)
|
||||
- [enum FsKind](../src/fs/plan.rs:1)
|
||||
- Values: Vfat, Btrfs, Bcachefs.
|
||||
- [struct FsSpec](src/fs/plan.rs:1)
|
||||
- [struct FsSpec](../src/fs/plan.rs:1)
|
||||
- Maps PartitionResult to desired filesystem kind and label (ZOSBOOT for ESP; ZOSDATA for all data filesystems including bcachefs).
|
||||
- [struct FsPlan](src/fs/plan.rs:1)
|
||||
- [struct FsPlan](../src/fs/plan.rs:1)
|
||||
- Plan of mkfs operations across all partitions and devices given the topology.
|
||||
- [struct FsResult](src/fs/plan.rs:1)
|
||||
- [struct FsResult](../src/fs/plan.rs:1)
|
||||
- Output of mkfs: device path(s), fs uuid, label, and kind.
|
||||
- [fn plan_filesystems(disks: &[Disk], parts: &[PartitionResult], cfg: &Config) -> Result<FsPlan>](src/fs/plan.rs:1)
|
||||
- [fn plan_filesystems(disks: &[Disk], parts: &[PartitionResult], cfg: &Config) -> Result<FsPlan>](../src/fs/plan.rs:1)
|
||||
- Determines which partitions receive vfat, btrfs, or bcachefs, and aggregates tuning options.
|
||||
- [fn make_filesystems(plan: &FsPlan) -> Result<Vec<FsResult>>](src/fs/plan.rs:1)
|
||||
- [fn make_filesystems(plan: &FsPlan, cfg: &Config) -> Result<Vec<FsResult>>](../src/fs/plan.rs:1)
|
||||
- Invokes mkfs.vfat, mkfs.btrfs, mkfs.bcachefs accordingly via utility wrappers and returns filesystem identities.
|
||||
|
||||
Mounting
|
||||
- [struct MountPlan](src/mount/ops.rs:1)
|
||||
- Derived from FsResult entries: creates target directories under /var/cache/<UUID> and the mounts required for the current boot.
|
||||
- [struct MountResult](src/mount/ops.rs:1)
|
||||
- [struct MountPlan](../src/mount/ops.rs:1)
|
||||
- Derived from FsResult entries. Plans:
|
||||
- Root mounts for all data filesystems under `/var/mounts/{UUID}` (runtime only).
|
||||
- btrfs root options: `rw,noatime,subvolid=5`
|
||||
- bcachefs root options: `rw,noatime`
|
||||
- Final subvolume/subdir mounts (from the primary data filesystem) to:
|
||||
- `/var/cache/system`, `/var/cache/etc`, `/var/cache/modules`, `/var/cache/vm-meta`
|
||||
- [struct MountResult](../src/mount/ops.rs:1)
|
||||
- Actual mount operations performed (source, target, fstype, options).
|
||||
- [fn plan_mounts(fs_results: &[FsResult], cfg: &Config) -> Result<MountPlan>](src/mount/ops.rs:1)
|
||||
- Translates filesystem identities to mount targets and options.
|
||||
- [fn apply_mounts(plan: &MountPlan) -> Result<Vec<MountResult>>](src/mount/ops.rs:1)
|
||||
- Performs mounts using syscalls (nix crate) with minimal dependencies. Ensures directories exist.
|
||||
- [fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config) -> Result<()>](src/mount/ops.rs:1)
|
||||
- When enabled, generates /etc/fstab entries in deterministic order. Disabled by default.
|
||||
- [fn plan_mounts(fs_results: &[FsResult], cfg: &Config) -> Result<MountPlan>](../src/mount/ops.rs:1)
|
||||
- Translates filesystem identities to mount targets and options, including `subvol=` for btrfs and `X-mount.subdir=` for bcachefs.
|
||||
- [fn apply_mounts(plan: &MountPlan) -> Result<Vec<MountResult>>](../src/mount/ops.rs:1)
|
||||
- Performs mounts using syscalls (nix crate). Ensures directories exist and creates subvolumes/subdirs if missing.
|
||||
- [fn maybe_write_fstab(mounts: &[MountResult], cfg: &Config) -> Result<()>](../src/mount/ops.rs:1)
|
||||
- When enabled, writes only the four subvolume/subdir mount entries to `/etc/fstab` in deterministic order using `UUID=` sources. Root mounts under `/var/mounts` are excluded.
|
||||
|
||||
Reporting
|
||||
- [const REPORT_VERSION: &str](src/report/state.rs:1)
|
||||
- [const REPORT_VERSION: &str](../src/report/state.rs:1)
|
||||
- Version string for the JSON payload schema.
|
||||
- [struct StateReport](src/report/state.rs:1)
|
||||
- [struct StateReport](../src/report/state.rs:1)
|
||||
- Machine-readable state describing discovered disks, created partitions, filesystems, labels, mountpoints, status, and timestamp.
|
||||
- [fn build_report(disks: &[Disk], parts: &[PartitionResult], fs: &[FsResult], mounts: &[MountResult], status: &str) -> StateReport](src/report/state.rs:1)
|
||||
- [fn build_report(disks: &[Disk], parts: &[PartitionResult], fs: &[FsResult], mounts: &[MountResult], status: &str) -> StateReport](../src/report/state.rs:1)
|
||||
- Constructs a StateReport matching REPORT_VERSION.
|
||||
- [fn write_report(report: &StateReport) -> Result<()>](src/report/state.rs:1)
|
||||
- [fn write_report(report: &StateReport) -> Result<()>](../src/report/state.rs:1)
|
||||
- Writes JSON to /run/zosstorage/state.json (configurable).
|
||||
|
||||
Idempotency
|
||||
- [fn detect_existing_state() -> Result<Option<StateReport>>](src/idempotency/mod.rs:1)
|
||||
- [fn detect_existing_state() -> Result<Option<StateReport>>](../src/idempotency/mod.rs:1)
|
||||
- Probes for expected GPT names (zosboot, zosdata, zoscache where applicable) and filesystem labels (ZOSBOOT, ZOSDATA). If present and consistent, returns a StateReport; orchestrator exits success without changes.
|
||||
- [fn is_empty_disk(disk: &Disk) -> Result<bool>](src/idempotency/mod.rs:1)
|
||||
- [fn is_empty_disk(disk: &Disk) -> Result<bool>](../src/idempotency/mod.rs:1)
|
||||
- Determines disk emptiness: absence of partitions and known filesystem signatures.
|
||||
|
||||
Utilities
|
||||
- [struct CmdOutput](src/util/mod.rs:1)
|
||||
- [struct CmdOutput](../src/util/mod.rs:1)
|
||||
- Captures status, stdout, stderr from external tool invocations.
|
||||
- [fn which_tool(name: &str) -> Result<Option<String>>](src/util/mod.rs:1)
|
||||
- [fn which_tool(name: &str) -> Result<Option<String>>](../src/util/mod.rs:1)
|
||||
- Locates a required system utility in PATH, returning its absolute path if available.
|
||||
- [fn run_cmd(args: &[&str]) -> Result<()>](src/util/mod.rs:1)
|
||||
- [fn run_cmd(args: &[&str]) -> Result<()>](../src/util/mod.rs:1)
|
||||
- Executes a command (args[0] is binary) and returns Ok when exit status is zero; logs stderr on failure.
|
||||
- [fn run_cmd_capture(args: &[&str]) -> Result<CmdOutput>](src/util/mod.rs:1)
|
||||
- [fn run_cmd_capture(args: &[&str]) -> Result<CmdOutput>](../src/util/mod.rs:1)
|
||||
- Executes a command and returns captured output for parsing (e.g., blkid).
|
||||
- [fn udev_settle(timeout_ms: u64) -> Result<()>](src/util/mod.rs:1)
|
||||
- [fn udev_settle(timeout_ms: u64) -> Result<()>](../src/util/mod.rs:1)
|
||||
- Calls udevadm settle with a timeout when available; otherwise no-ops with a warning.
|
||||
- [fn is_efi_boot() -> bool](../src/util/mod.rs:1)
|
||||
- Detects UEFI environment by checking `/sys/firmware/efi`; used to suppress BIOS boot partition creation on UEFI systems.
|
||||
|
||||
Behavioral notes and contracts
|
||||
- Safety and idempotency:
|
||||
@@ -188,10 +198,13 @@ Behavioral notes and contracts
|
||||
- Data filesystems use label ZOSDATA regardless of backend kind.
|
||||
- Cache partitions in bcachefs topology use GPT name zoscache.
|
||||
- Topology-specific behavior:
|
||||
- single: one data filesystem (btrfs) on the sole disk.
|
||||
- dual_independent: two separate btrfs filesystems, one per disk.
|
||||
- btrfs_single: one data filesystem (btrfs) on the sole disk.
|
||||
- bcachefs_single: one data filesystem (bcachefs) on the sole disk.
|
||||
- dual_independent: independent btrfs filesystems on each eligible disk (one or more).
|
||||
- bcachefs2_copy: multi-device bcachefs across two or more data partitions with `--replicas=2` (data and metadata).
|
||||
- ssd_hdd_bcachefs: bcachefs spanning SSD (cache/promote) and HDD (backing), labeled ZOSDATA.
|
||||
- btrfs_raid1: only when explicitly requested; otherwise default to independent btrfs.
|
||||
- UEFI vs BIOS: when running under UEFI (`/sys/firmware/efi` present), the BIOS boot partition is suppressed.
|
||||
|
||||
Module dependency overview
|
||||
|
||||
|
||||
@@ -30,116 +30,122 @@ Top level
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [src/lib.rs](../src/lib.rs)
|
||||
- Crate exports, prelude, version constants, Result alias.
|
||||
- [src/errors.rs](src/errors.rs)
|
||||
- [src/errors.rs](../src/errors.rs)
|
||||
- Common error enum and Result alias via thiserror.
|
||||
- [src/cli/args.rs](src/cli/args.rs)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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/<UUID>. Optional fstab writing, disabled by default.
|
||||
- [src/report/state.rs](src/report/state.rs)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [enum Error](../src/errors.rs:1)
|
||||
- [type Result<T> = std::result::Result<T, Error>](../src/errors.rs:1)
|
||||
|
||||
Execution flow
|
||||
|
||||
@@ -190,8 +196,15 @@ Filesystem provisioning defaults
|
||||
- Filesystem tuning options configurable with sensible defaults and extension points
|
||||
|
||||
Mount scheme and fstab policy
|
||||
- Mount under /var/cache/<UUID> using filesystem UUID to create stable subdirectories
|
||||
- Optional /etc/fstab generation disabled by default; when enabled, produce deterministic order with documentation
|
||||
- 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
|
||||
|
||||
@@ -8,18 +8,18 @@ Goal
|
||||
Core Principles
|
||||
1) Contract-first per module
|
||||
- API signatures and responsibilities are documented in [docs/API-SKELETONS.md](docs/API-SKELETONS.md) and mirrored by crate modules:
|
||||
- [src/types.rs](src/types.rs)
|
||||
- [fn load_and_merge()](src/config/loader.rs:1), [fn validate()](src/config/loader.rs:1)
|
||||
- [fn from_args()](src/cli/args.rs:1)
|
||||
- [struct LogOptions](src/logging/mod.rs:1), [fn init_logging()](src/logging/mod.rs:1)
|
||||
- [fn discover()](src/device/discovery.rs:1)
|
||||
- [fn plan_partitions()](src/partition/plan.rs:1), [fn apply_partitions()](src/partition/plan.rs:1)
|
||||
- [fn plan_filesystems()](src/fs/plan.rs:1), [fn make_filesystems()](src/fs/plan.rs:1)
|
||||
- [fn plan_mounts()](src/mount/ops.rs:1), [fn apply_mounts()](src/mount/ops.rs:1), [fn maybe_write_fstab()](src/mount/ops.rs:1)
|
||||
- [const REPORT_VERSION](src/report/state.rs:1), [fn build_report()](src/report/state.rs:1), [fn write_report()](src/report/state.rs:1)
|
||||
- [struct Context](src/orchestrator/run.rs:1), [fn run()](src/orchestrator/run.rs:1)
|
||||
- [fn detect_existing_state()](src/idempotency/mod.rs:1), [fn is_empty_disk()](src/idempotency/mod.rs:1)
|
||||
- [struct CmdOutput](src/util/mod.rs:1), [fn which_tool()](src/util/mod.rs:1), [fn run_cmd()](src/util/mod.rs:1), [fn run_cmd_capture()](src/util/mod.rs:1), [fn udev_settle()](src/util/mod.rs:1)
|
||||
- [src/types.rs](../src/types.rs)
|
||||
- [fn load_and_merge()](../src/config/loader.rs:1), [fn validate()](../src/config/loader.rs:1)
|
||||
- [fn from_args()](../src/cli/args.rs:1)
|
||||
- [struct LogOptions](../src/logging/mod.rs:1), [fn init_logging()](../src/logging/mod.rs:1)
|
||||
- [fn discover()](../src/device/discovery.rs:1)
|
||||
- [fn plan_partitions()](../src/partition/plan.rs:1), [fn apply_partitions()](../src/partition/plan.rs:1)
|
||||
- [fn plan_filesystems()](../src/fs/plan.rs:1), [fn make_filesystems()](../src/fs/plan.rs:1)
|
||||
- [fn plan_mounts()](../src/mount/ops.rs:1), [fn apply_mounts()](../src/mount/ops.rs:1), [fn maybe_write_fstab()](../src/mount/ops.rs:1)
|
||||
- [const REPORT_VERSION](../src/report/state.rs:1), [fn build_report()](../src/report/state.rs:1), [fn write_report()](../src/report/state.rs:1)
|
||||
- [struct Context](../src/orchestrator/run.rs:1), [fn run()](../src/orchestrator/run.rs:1)
|
||||
- [fn detect_existing_state()](../src/idempotency/mod.rs:1), [fn is_empty_disk()](../src/idempotency/mod.rs:1)
|
||||
- [struct CmdOutput](../src/util/mod.rs:1), [fn which_tool()](../src/util/mod.rs:1), [fn run_cmd()](../src/util/mod.rs:1), [fn run_cmd_capture()](../src/util/mod.rs:1), [fn udev_settle()](../src/util/mod.rs:1)
|
||||
|
||||
2) Grep-able region markers in code
|
||||
- Every module contains the following optional annotated regions:
|
||||
@@ -55,22 +55,22 @@ Core Principles
|
||||
6) Module ownership and boundaries
|
||||
- Add a “Module Responsibilities” section in each module’s header doc comment summarizing scope and non-goals.
|
||||
- Example references:
|
||||
- [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/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)
|
||||
|
||||
7) Invariants and safety notes
|
||||
- For code that must uphold safety or idempotency invariants, annotate with:
|
||||
// SAFETY: explanation
|
||||
// IDEMPOTENCY: explanation
|
||||
- Example locations:
|
||||
- [fn apply_partitions()](src/partition/plan.rs:1) must enforce empty-disks rule when configured.
|
||||
- [fn make_filesystems()](src/fs/plan.rs:1) must not run if partitioning failed.
|
||||
- [fn apply_partitions()](../src/partition/plan.rs:1) must enforce empty-disks rule when configured.
|
||||
- [fn make_filesystems()](../src/fs/plan.rs:1) must not run if partitioning failed.
|
||||
|
||||
8) Error mapping consistency
|
||||
- Centralize conversions to [enum Error](src/errors.rs:1). When calling external tools, wrap failures into Error::Tool with stderr captured.
|
||||
- Centralize conversions to [enum Error](../src/errors.rs:1). When calling external tools, wrap failures into Error::Tool with stderr captured.
|
||||
- Annotate mapping areas with:
|
||||
// ERROR: mapping external failure to Error::Tool
|
||||
|
||||
@@ -111,7 +111,7 @@ Checklist for adding a new feature
|
||||
- Add examples if config or output formats change
|
||||
- Update [config/zosstorage.example.yaml](config/zosstorage.example.yaml) or add a new example file
|
||||
- Keep error mapping and logging consistent:
|
||||
- Ensure any external tool calls map errors to [enum Error](src/errors.rs:1)
|
||||
- Ensure any external tool calls map errors to [enum Error](../src/errors.rs:1)
|
||||
- Run cargo build and update any broken references
|
||||
|
||||
Optional automation (future)
|
||||
|
||||
@@ -43,7 +43,7 @@ device_selection:
|
||||
allow_removable: false # future option; default false
|
||||
min_size_gib: 10 # ignore devices smaller than this (default 10)
|
||||
topology: # desired overall layout; see values below
|
||||
mode: single # single | dual_independent | ssd_hdd_bcachefs | btrfs_raid1 (optional)
|
||||
mode: btrfs_single # btrfs_single | bcachefs_single | dual_independent | bcachefs2_copy | ssd_hdd_bcachefs | btrfs_raid1
|
||||
partitioning:
|
||||
alignment_mib: 1 # GPT alignment in MiB
|
||||
require_empty_disks: true # abort if any partition or FS signatures exist
|
||||
@@ -83,8 +83,8 @@ report:
|
||||
Topology modes
|
||||
- btrfs_single: One eligible disk. Create BIOS boot (if enabled), ESP 512 MiB, remainder as data. Create a btrfs filesystem labeled ZOSDATA on the data partition.
|
||||
- bcachefs_single: One eligible disk. Create BIOS boot (if enabled), ESP 512 MiB, remainder as data. Create a bcachefs filesystem labeled ZOSDATA on the data partition.
|
||||
- dual_independent: Two eligible disks. On each disk, create BIOS boot (if enabled) + ESP + data. Create an independent btrfs filesystem labeled ZOSDATA on each data partition. No RAID by default.
|
||||
- bcachefs_2copy: Two eligible disks. Create data partitions on both, then create a single multi-device bcachefs labeled ZOSDATA spanning the data partitions (two-copies semantics to be tuned via mkfs options in a follow-up).
|
||||
- dual_independent: One or more eligible disks. On each disk, create BIOS boot (if enabled) + ESP + data. Create an independent btrfs filesystem labeled ZOSDATA on each data partition. No RAID by default.
|
||||
- bcachefs2_copy: Two or more eligible disks (minimum 2). Create data partitions and then a single multi-device bcachefs labeled ZOSDATA spanning those data partitions. The mkfs step uses `--replicas=2` (data and metadata).
|
||||
- ssd_hdd_bcachefs: One SSD/NVMe and one HDD. Create BIOS boot (if enabled) + ESP on both as required. Create cache (on SSD) and data/backing (on HDD) partitions named zoscache and zosdata respectively. Create a bcachefs labeled ZOSDATA across SSD(HDD) per policy (SSD cache/promote; HDD backing).
|
||||
- btrfs_raid1: Optional mode if explicitly requested. Create mirrored btrfs across two disks for the data role with raid1 profile. Not enabled by default.
|
||||
|
||||
@@ -119,11 +119,15 @@ Filesystem section
|
||||
- vfat: label ZOSBOOT used for ESP.
|
||||
|
||||
Mount section
|
||||
- base_dir: default /var/cache.
|
||||
- scheme:
|
||||
- per_uuid: mount data filesystems at /var/cache/<FS-UUID>
|
||||
- custom: reserved for future mapping-by-config, not yet implemented.
|
||||
- fstab.enabled: default false. When true, zosstorage will generate fstab entries in deterministic order.
|
||||
- Runtime root mounts (all data filesystems):
|
||||
- Each data filesystem is root-mounted at `/var/mounts/{UUID}`
|
||||
- btrfs root mount options: `rw,noatime,subvolid=5`
|
||||
- bcachefs root mount options: `rw,noatime`
|
||||
- Subvolume mounts (from the primary data filesystem only) to final targets:
|
||||
- Targets: `/var/cache/system`, `/var/cache/etc`, `/var/cache/modules`, `/var/cache/vm-meta`
|
||||
- btrfs subvol options: `-o rw,noatime,subvol={name}`
|
||||
- bcachefs subdir options: `-o rw,noatime,X-mount.subdir={name}`
|
||||
- fstab.enabled: default false. When true, zosstorage writes only the four subvolume mount entries, in deterministic target order, using `UUID=` sources for the filesystem; root mounts under `/var/mounts` are excluded.
|
||||
|
||||
Report section
|
||||
- path: default /run/zosstorage/state.json.
|
||||
@@ -135,7 +139,7 @@ Minimal single-disk btrfs
|
||||
```yaml
|
||||
version: 1
|
||||
topology:
|
||||
mode: single
|
||||
mode: btrfs_single
|
||||
```
|
||||
|
||||
Dual independent btrfs (two disks)
|
||||
@@ -186,15 +190,15 @@ Future extensions
|
||||
- Multiple topology groups on multi-disk systems
|
||||
|
||||
Reference modules
|
||||
- [src/types.rs](src/types.rs)
|
||||
- [src/config/loader.rs](src/config/loader.rs)
|
||||
- [src/cli/args.rs](src/cli/args.rs)
|
||||
- [src/orchestrator/run.rs](src/orchestrator/run.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/idempotency/mod.rs](src/idempotency/mod.rs)
|
||||
- [src/types.rs](../src/types.rs)
|
||||
- [src/config/loader.rs](../src/config/loader.rs)
|
||||
- [src/cli/args.rs](../src/cli/args.rs)
|
||||
- [src/orchestrator/run.rs](../src/orchestrator/run.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/idempotency/mod.rs](../src/idempotency/mod.rs)
|
||||
|
||||
Change log
|
||||
- v1: Initial draft of schema and precedence rules
|
||||
|
||||
127
docs/SPECS.md
127
docs/SPECS.md
@@ -3,31 +3,31 @@
|
||||
This document finalizes core specifications required before code skeleton implementation. It complements [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) and [docs/SCHEMA.md](docs/SCHEMA.md), and references the API declarations listed in [docs/API.md](docs/API.md).
|
||||
|
||||
Linked modules and functions
|
||||
- Logging module: [src/logging/mod.rs](src/logging/mod.rs)
|
||||
- [fn init_logging(opts: &LogOptions) -> Result<()>](src/logging/mod.rs:1)
|
||||
- Report module: [src/report/state.rs](src/report/state.rs)
|
||||
- [const REPORT_VERSION: &str](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)
|
||||
- Device module: [src/device/discovery.rs](src/device/discovery.rs)
|
||||
- [fn discover(filter: &DeviceFilter) -> Result<Vec<Disk>>](src/device/discovery.rs:1)
|
||||
- Partitioning module: [src/partition/plan.rs](src/partition/plan.rs)
|
||||
- [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 module: [src/fs/plan.rs](src/fs/plan.rs)
|
||||
- [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)
|
||||
- Mount module: [src/mount/ops.rs](src/mount/ops.rs)
|
||||
- [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)
|
||||
- Idempotency module: [src/idempotency/mod.rs](src/idempotency/mod.rs)
|
||||
- [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)
|
||||
- CLI module: [src/cli/args.rs](src/cli/args.rs)
|
||||
- [fn from_args() -> Cli](src/cli/args.rs:1)
|
||||
- Orchestrator: [src/orchestrator/run.rs](src/orchestrator/run.rs)
|
||||
- [fn run(ctx: &Context) -> Result<()>](src/orchestrator/run.rs:1)
|
||||
- Logging module: [src/logging/mod.rs](../src/logging/mod.rs)
|
||||
- [fn init_logging(opts: &LogOptions) -> Result<()>](../src/logging/mod.rs:1)
|
||||
- Report module: [src/report/state.rs](../src/report/state.rs)
|
||||
- [const REPORT_VERSION: &str](../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)
|
||||
- Device module: [src/device/discovery.rs](../src/device/discovery.rs)
|
||||
- [fn discover(filter: &DeviceFilter) -> Result<Vec<Disk>>](../src/device/discovery.rs:1)
|
||||
- Partitioning module: [src/partition/plan.rs](../src/partition/plan.rs)
|
||||
- [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 module: [src/fs/plan.rs](../src/fs/plan.rs)
|
||||
- [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)
|
||||
- Mount module: [src/mount/ops.rs](../src/mount/ops.rs)
|
||||
- [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)
|
||||
- Idempotency module: [src/idempotency/mod.rs](../src/idempotency/mod.rs)
|
||||
- [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)
|
||||
- CLI module: [src/cli/args.rs](../src/cli/args.rs)
|
||||
- [fn from_args() -> Cli](../src/cli/args.rs:1)
|
||||
- Orchestrator: [src/orchestrator/run.rs](../src/orchestrator/run.rs)
|
||||
- [fn run(ctx: &Context) -> Result<()>](../src/orchestrator/run.rs:1)
|
||||
|
||||
---
|
||||
|
||||
@@ -39,7 +39,7 @@ Goals
|
||||
|
||||
Configuration
|
||||
- Levels: error, warn, info, debug (default info).
|
||||
- Propagation: single global initialization via [fn init_logging](src/logging/mod.rs:1). Subsequent calls must be no-ops.
|
||||
- Propagation: single global initialization via [fn init_logging](../src/logging/mod.rs:1). Subsequent calls must be no-ops.
|
||||
|
||||
Implementation notes
|
||||
- Use tracing and tracing-subscriber.
|
||||
@@ -57,7 +57,7 @@ Location
|
||||
- Default output: /run/zosstorage/state.json
|
||||
|
||||
Versioning
|
||||
- Include a top-level string field version equal to [REPORT_VERSION](src/report/state.rs:1). Start with v1.
|
||||
- Include a top-level string field version equal to [REPORT_VERSION](../src/report/state.rs:1). Start with v1.
|
||||
|
||||
Schema example
|
||||
|
||||
@@ -154,17 +154,17 @@ Default exclude patterns
|
||||
- ^/dev/fd\\d+$
|
||||
|
||||
Selection policy
|
||||
- Compile include and exclude regex into [DeviceFilter](src/device/discovery.rs).
|
||||
- Compile include and exclude regex into [DeviceFilter](../src/device/discovery.rs).
|
||||
- Enumerate device candidates and apply:
|
||||
- Must match at least one include.
|
||||
- Must not match any exclude.
|
||||
- Must be larger than min_size_gib (default 10).
|
||||
- Probing
|
||||
- Gather size, rotational flag, model, serial when available.
|
||||
- Expose via [struct Disk](src/device/discovery.rs:1).
|
||||
- Expose via [struct Disk](../src/device/discovery.rs:1).
|
||||
|
||||
No eligible disks
|
||||
- Return a specific error variant in [enum Error](src/errors.rs:1).
|
||||
- Return a specific error variant in [enum Error](../src/errors.rs:1).
|
||||
|
||||
---
|
||||
|
||||
@@ -181,17 +181,20 @@ Layout defaults
|
||||
- Cache partitions (only in ssd_hdd_bcachefs): GPT name zoscache on SSD.
|
||||
|
||||
Per-topology specifics
|
||||
- single: All roles on the single disk.
|
||||
- dual_independent: Each disk gets BIOS boot + ESP + data.
|
||||
- ssd_hdd_bcachefs: SSD gets BIOS boot + ESP + zoscache, HDD gets BIOS boot + ESP + zosdata.
|
||||
- btrfs_single: All roles on the single disk; data formatted as btrfs.
|
||||
- bcachefs_single: All roles on the single disk; data formatted as bcachefs.
|
||||
- dual_independent: On each eligible disk (one or more), create BIOS boot (if applicable), ESP, and data.
|
||||
- bcachefs_2copy: Create data partitions on two or more disks; later formatted as one multi-device bcachefs spanning all data partitions.
|
||||
- ssd_hdd_bcachefs: SSD gets BIOS boot + ESP + zoscache; HDD gets BIOS boot + ESP + zosdata; combined later into one bcachefs.
|
||||
- btrfs_raid1: Two disks minimum; data partitions mirrored via btrfs RAID1.
|
||||
|
||||
Safety checks
|
||||
- Ensure unique partition UUIDs.
|
||||
- Verify no pre-existing partitions or signatures. Use blkid or similar via [run_cmd_capture](src/util/mod.rs:1).
|
||||
- After partition creation, run udev settle via [udev_settle](src/util/mod.rs:1).
|
||||
- Verify no pre-existing partitions or signatures. Use blkid or similar via [run_cmd_capture](../src/util/mod.rs:1).
|
||||
- After partition creation, run udev settle via [udev_settle](../src/util/mod.rs:1).
|
||||
|
||||
Application
|
||||
- Utilize sgdisk helpers in [apply_partitions](src/partition/plan.rs:1).
|
||||
- Utilize sgdisk helpers in [apply_partitions](../src/partition/plan.rs:1).
|
||||
|
||||
---
|
||||
|
||||
@@ -199,34 +202,38 @@ Application
|
||||
|
||||
Kinds
|
||||
- Vfat for ESP, label ZOSBOOT.
|
||||
- Btrfs for data on single and dual_independent.
|
||||
- Bcachefs for ssd_hdd_bcachefs (SSD cache, HDD backing).
|
||||
- Btrfs for data in btrfs_single, dual_independent, and btrfs_raid1 (with RAID1 profile).
|
||||
- Bcachefs for data in bcachefs_single, ssd_hdd_bcachefs (SSD cache + HDD backing), and bcachefs_2copy (multi-device).
|
||||
- All data filesystems use label ZOSDATA.
|
||||
|
||||
Defaults
|
||||
- btrfs: compression zstd:3, raid_profile none unless explicitly set to raid1 in btrfs_raid1 mode.
|
||||
- bcachefs: cache_mode promote, compression zstd, checksum crc32c.
|
||||
- btrfs: compression zstd:3, raid_profile none unless explicitly set; for btrfs_raid1 use -m raid1 -d raid1.
|
||||
- bcachefs: cache_mode promote, compression zstd, checksum crc32c; for bcachefs_2copy use `--replicas=2` (data and metadata).
|
||||
- vfat: ESP label ZOSBOOT.
|
||||
|
||||
Planning and execution
|
||||
- Decide mapping of [PartitionResult](src/partition/plan.rs:1) to [FsSpec](src/fs/plan.rs:1) in [plan_filesystems](src/fs/plan.rs:1).
|
||||
- Create filesystems in [make_filesystems](src/fs/plan.rs:1) through wrapped mkfs tools.
|
||||
- Capture resulting identifiers (fs uuid, label) in [FsResult](src/fs/plan.rs:1).
|
||||
- Decide mapping of [PartitionResult](../src/partition/plan.rs:1) to [FsSpec](../src/fs/plan.rs:1) in [plan_filesystems](../src/fs/plan.rs:1).
|
||||
- Create filesystems in [make_filesystems](../src/fs/plan.rs:1) through wrapped mkfs tools.
|
||||
- Capture resulting identifiers (fs uuid, label) in [FsResult](../src/fs/plan.rs:1).
|
||||
|
||||
---
|
||||
|
||||
## 6. Mount scheme and fstab policy
|
||||
|
||||
Scheme
|
||||
- per_uuid under /var/cache: directories named as filesystem UUIDs.
|
||||
Runtime root mounts (all data filesystems)
|
||||
- Each data filesystem is root-mounted at `/var/mounts/{UUID}` (runtime only).
|
||||
- btrfs root mount options: `rw,noatime,subvolid=5`
|
||||
- bcachefs root mount options: `rw,noatime`
|
||||
|
||||
Mount options
|
||||
- btrfs: ssd when non-rotational underlying device, compress from config, defaults otherwise.
|
||||
- vfat: defaults, utf8.
|
||||
Final subvolume/subdir mounts (from the primary data filesystem)
|
||||
- Create or ensure subvolumes named: `system`, `etc`, `modules`, `vm-meta`
|
||||
- Mount targets: `/var/cache/system`, `/var/cache/etc`, `/var/cache/modules`, `/var/cache/vm-meta`
|
||||
- btrfs options: `-o rw,noatime,subvol={name}`
|
||||
- bcachefs options: `-o rw,noatime,X-mount.subdir={name}`
|
||||
|
||||
fstab
|
||||
fstab policy
|
||||
- Disabled by default.
|
||||
- When enabled, [maybe_write_fstab](src/mount/ops.rs:1) writes deterministic entries sorted by target path.
|
||||
- When enabled, [maybe_write_fstab](../src/mount/ops.rs:1) writes only the four final subvolume/subdir entries using `UUID=` sources, in deterministic target order. Root mounts under `/var/mounts` are excluded.
|
||||
|
||||
---
|
||||
|
||||
@@ -235,20 +242,23 @@ fstab
|
||||
Signals for already-provisioned system
|
||||
- Expected GPT names found: zosboot, zosdata, and zoscache when applicable.
|
||||
- Filesystems with labels ZOSBOOT for ESP and ZOSDATA for all data filesystems.
|
||||
- When consistent with selected topology, [detect_existing_state](src/idempotency/mod.rs:1) returns a StateReport and orchestrator exits success without changes.
|
||||
- When consistent with selected topology, [detect_existing_state](../src/idempotency/mod.rs:1) returns a StateReport and orchestrator exits success without changes.
|
||||
|
||||
Disk emptiness
|
||||
- [is_empty_disk](src/idempotency/mod.rs:1) checks for absence of partitions and FS signatures before any modification.
|
||||
- [is_empty_disk](../src/idempotency/mod.rs:1) checks for absence of partitions and FS signatures before any modification.
|
||||
|
||||
---
|
||||
|
||||
## 8. CLI flags and help text outline
|
||||
|
||||
Flags mirrored by [struct Cli](src/cli/args.rs:1) parsed via [from_args](src/cli/args.rs:1)
|
||||
Flags mirrored by [struct Cli](../src/cli/args.rs:1) parsed via [from_args](../src/cli/args.rs:1)
|
||||
- --config PATH
|
||||
- --log-level LEVEL error | warn | info | debug
|
||||
- --log-to-file
|
||||
- --fstab enable fstab generation
|
||||
- --show print preview JSON to stdout (non-destructive)
|
||||
- --report PATH write preview JSON to file (non-destructive)
|
||||
- --apply perform partitioning, filesystem creation, and mounts (DESTRUCTIVE)
|
||||
- --force present but returns unimplemented error
|
||||
|
||||
Kernel cmdline
|
||||
@@ -257,7 +267,7 @@ Kernel cmdline
|
||||
Help text sections
|
||||
- NAME, SYNOPSIS, DESCRIPTION
|
||||
- CONFIG PRECEDENCE
|
||||
- TOPOLOGIES: single, dual_independent, ssd_hdd_bcachefs, btrfs_raid1
|
||||
- TOPOLOGIES: btrfs_single, bcachefs_single, dual_independent, bcachefs_2copy, ssd_hdd_bcachefs, btrfs_raid1
|
||||
- SAFETY AND IDEMPOTENCY
|
||||
- REPORTS
|
||||
- EXIT CODES: 0 success or already_provisioned, non-zero on error
|
||||
@@ -267,9 +277,10 @@ Help text sections
|
||||
## 9. Integration testing plan (QEMU KVM)
|
||||
|
||||
Scenarios to scaffold in [tests/](tests/)
|
||||
- Single disk 40 GiB virtio: validates single topology end-to-end smoke.
|
||||
- Dual NVMe 40 GiB each: validates dual_independent topology.
|
||||
- SSD NVMe + HDD virtio: validates ssd_hdd_bcachefs topology.
|
||||
- Single disk 40 GiB virtio: validates btrfs_single topology end-to-end smoke.
|
||||
- Dual NVMe 40 GiB each: validates dual_independent topology (independent btrfs per disk).
|
||||
- SSD NVMe + HDD virtio: validates ssd_hdd_bcachefs topology (bcachefs with SSD cache/promote, HDD backing).
|
||||
- Three disks: validates bcachefs_2copy across data partitions using `--replicas=2`.
|
||||
- Negative: no eligible disks, or non-empty disk should abort.
|
||||
|
||||
Test strategy
|
||||
@@ -281,7 +292,7 @@ Test strategy
|
||||
Artifacts to validate
|
||||
- Presence of expected partition GPT names.
|
||||
- Filesystems created with correct labels.
|
||||
- Mountpoints under /var/cache/<UUID> when running in a VM.
|
||||
- Runtime root mounts under `/var/mounts/{UUID}` and final subvolume targets at `/var/cache/{system,etc,modules,vm-meta}`.
|
||||
- JSON report validates against v1 schema.
|
||||
|
||||
---
|
||||
|
||||
@@ -47,14 +47,14 @@ Consequences
|
||||
|
||||
Implementation Notes
|
||||
- Region markers have been added to key modules:
|
||||
- [src/config/loader.rs](src/config/loader.rs)
|
||||
- [src/orchestrator/run.rs](src/orchestrator/run.rs)
|
||||
- [src/cli/args.rs](src/cli/args.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/config/loader.rs](../src/config/loader.rs)
|
||||
- [src/orchestrator/run.rs](../src/orchestrator/run.rs)
|
||||
- [src/cli/args.rs](../src/cli/args.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)
|
||||
- Remaining modules will follow the same pattern as needed (e.g., util, idempotency, main/lib if helpful).
|
||||
|
||||
Related Documents
|
||||
|
||||
Reference in New Issue
Block a user