feat: first-draft preview-capable zosstorage

- CLI: add topology selection (-t/--topology), preview flags (--show/--report), and removable policy override (--allow-removable) (src/cli/args.rs)
- Config: built-in sensible defaults; deterministic overlays for logging, fstab, removable, topology (src/config/loader.rs)
- Device: discovery via /proc + /sys with include/exclude regex and removable policy (src/device/discovery.rs)
- Idempotency: detection via blkid; safe emptiness checks (src/idempotency/mod.rs)
- Partition: topology-driven planning (Single, DualIndependent, BtrfsRaid1, SsdHddBcachefs) (src/partition/plan.rs)
- FS: planning + creation (mkfs.vfat, mkfs.btrfs, bcachefs format) and UUID capture via blkid (src/fs/plan.rs)
- Orchestrator: pre-flight with preview JSON (disks, partition_plan, filesystems_planned, mount scheme). Skips emptiness in preview; supports stdout+file (src/orchestrator/run.rs)
- Util/Logging/Types/Errors: process execution, tracing, shared types (src/util/mod.rs, src/logging/mod.rs, src/types.rs, src/errors.rs)
- Docs: add README with exhaustive usage and preview JSON shape (README.md)

Builds and unit tests pass: discovery, util, idempotency helpers, and fs parser tests.
This commit is contained in:
2025-09-29 11:37:07 +02:00
commit 507bc172c2
38 changed files with 6558 additions and 0 deletions

170
src/types.rs Normal file
View File

@@ -0,0 +1,170 @@
//! Typed configuration schema for zosstorage.
//!
//! Mirrors docs in [docs/SCHEMA.md](docs/SCHEMA.md) and is loaded/validated by
//! [fn load_and_merge()](src/config/loader.rs:1) and [fn validate()](src/config/loader.rs:1).
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingConfig {
/// Log level: "error" | "warn" | "info" | "debug"
pub level: String, // default "info"
/// When true, also log to /run/zosstorage/zosstorage.log
pub to_file: bool, // default false
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceSelection {
/// Regex patterns to include device paths (Rust regex).
pub include_patterns: Vec<String>,
/// Regex patterns to exclude device paths.
pub exclude_patterns: Vec<String>,
/// Whether to include removable devices (future).
pub allow_removable: bool,
/// Minimum device size (GiB) to consider eligible.
pub min_size_gib: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Topology {
/// Single eligible disk; btrfs on remainder.
Single,
/// Two eligible disks; independent btrfs on each data partition.
DualIndependent,
/// SSD + HDD; bcachefs with SSD cache/promote and HDD backing.
SsdHddBcachefs,
/// Optional mirrored btrfs across two disks when explicitly requested.
BtrfsRaid1,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BiosBootSpec {
/// Whether to create a tiny BIOS boot partition.
pub enabled: bool,
/// Size in MiB (default 1).
pub size_mib: u64,
/// GPT partition name (e.g., "zosboot").
pub gpt_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EspSpec {
/// ESP size in MiB (default 512).
pub size_mib: u64,
/// Filesystem label for ESP (ZOSBOOT).
pub label: String,
/// GPT partition name (e.g., "zosboot").
pub gpt_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataSpec {
/// GPT partition name for data (e.g., "zosdata").
pub gpt_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheSpec {
/// GPT partition name for cache partitions (e.g., "zoscache").
pub gpt_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Partitioning {
/// Alignment in MiB (default 1 MiB).
pub alignment_mib: u64,
/// Abort if any target disk is not empty (default true).
pub require_empty_disks: bool,
/// BIOS boot partition spec.
pub bios_boot: BiosBootSpec,
/// ESP partition spec.
pub esp: EspSpec,
/// Data partition spec.
pub data: DataSpec,
/// Cache partition spec (only in ssd_hdd_bcachefs).
pub cache: CacheSpec,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BtrfsOptions {
/// Filesystem label (ZOSDATA).
pub label: String,
/// Compression string (e.g., "zstd:3").
pub compression: String,
/// "none" | "raid1"
pub raid_profile: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BcachefsOptions {
/// Filesystem label (ZOSDATA).
pub label: String,
/// "promote" | "writeback" (if supported).
pub cache_mode: String,
/// Compression algorithm (e.g., "zstd").
pub compression: String,
/// Checksum algorithm (e.g., "crc32c").
pub checksum: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VfatOptions {
/// Filesystem label (ZOSBOOT).
pub label: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FsOptions {
/// btrfs tuning.
pub btrfs: BtrfsOptions,
/// bcachefs tuning.
pub bcachefs: BcachefsOptions,
/// vfat tuning for ESP.
pub vfat: VfatOptions,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MountSchemeKind {
/// Mount under /var/cache/<UUID>
PerUuid,
/// Reserved for future custom mappings.
Custom,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MountScheme {
/// Base directory (default: /var/cache).
pub base_dir: String,
/// Scheme kind (PerUuid | Custom (reserved)).
pub scheme: MountSchemeKind,
/// When true, write /etc/fstab entries (disabled by default).
pub fstab_enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReportOptions {
/// Path for JSON state report (default: /run/zosstorage/state.json).
pub path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
/// Schema version (start at 1).
pub version: u32,
/// Logging configuration.
pub logging: LoggingConfig,
/// Device selection and filtering rules.
pub device_selection: DeviceSelection,
/// Desired topology mode.
pub topology: Topology,
/// Partitioning parameters.
pub partitioning: Partitioning,
/// Filesystem options and tuning.
pub filesystem: FsOptions,
/// Mount scheme and fstab policy.
pub mount: MountScheme,
/// Report output configuration.
pub report: ReportOptions,
}