// REGION: API // api: cli::LogLevelArg { Error, Warn, Info, Debug } // api: cli::Cli { config: Option, log_level: LogLevelArg, log_to_file: bool, fstab: bool, force: bool } // api: cli::from_args() -> crate::cli::Cli // REGION: API-END // // REGION: RESPONSIBILITIES // - Define non-interactive CLI flags mirroring kernel cmdline semantics. // - Provide a stable parsing entry (from_args) suitable for initramfs. // Non-goals: config validation, IO, or side effects beyond parsing. // REGION: RESPONSIBILITIES-END // // REGION: EXTENSION_POINTS // ext: add --dry-run to support planning without changes (future). // ext: add --report-path to override JSON report location (future). // REGION: EXTENSION_POINTS-END // // REGION: SAFETY // safety: no interactive prompts; default values are explicit; parsing errors should be clear. // REGION: SAFETY-END // // REGION: ERROR_MAPPING // errmap: clap parsing errors are emitted by clap; higher layers should handle exit strategy. // REGION: ERROR_MAPPING-END // // REGION: TODO // todo: consider hidden/unstable flags gated by build features for developers. // REGION: TODO-END //! CLI definition mirroring kernel cmdline semantics; non-interactive. use clap::{Parser, ValueEnum}; #[derive(Debug, Clone, Copy, ValueEnum)] #[value(rename_all = "kebab_case")] pub enum LogLevelArg { Error, Warn, Info, Debug, } impl std::fmt::Display for LogLevelArg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { LogLevelArg::Error => "error", LogLevelArg::Warn => "warn", LogLevelArg::Info => "info", LogLevelArg::Debug => "debug", }; f.write_str(s) } } /// Topology argument (maps to config Topology with snake_case semantics). #[derive(Debug, Clone, Copy, ValueEnum)] #[value(rename_all = "kebab_case")] pub enum TopologyArg { Single, DualIndependent, SsdHddBcachefs, BtrfsRaid1, } impl std::fmt::Display for TopologyArg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { TopologyArg::Single => "single", TopologyArg::DualIndependent => "dual_independent", TopologyArg::SsdHddBcachefs => "ssd_hdd_bcachefs", TopologyArg::BtrfsRaid1 => "btrfs_raid1", }; f.write_str(s) } } /// zosstorage - one-shot disk initializer for initramfs. #[derive(Debug, Parser)] #[command(name = "zosstorage", disable_help_subcommand = true)] pub struct Cli { /// Path to YAML configuration (mirrors kernel cmdline key 'zosstorage.config=') #[arg(short = 'c', long = "config")] pub config: Option, /// Log level: error, warn, info, debug #[arg(short = 'l', long = "log-level", value_enum, default_value_t = LogLevelArg::Info)] pub log_level: LogLevelArg, /// Also log to /run/zosstorage/zosstorage.log #[arg(short = 'L', long = "log-to-file", default_value_t = false)] pub log_to_file: bool, /// Enable writing /etc/fstab entries #[arg(short = 's', long = "fstab", default_value_t = false)] pub fstab: bool, /// Select topology (overrides config topology) #[arg(short = 't', long = "topology", value_enum)] pub topology: Option, /// Present but non-functional; returns unimplemented error #[arg(short = 'f', long = "force")] pub force: bool, /// Allow removable devices (e.g., USB sticks) to be considered during discovery /// Overrides config.device_selection.allow_removable when provided #[arg(long = "allow-removable", default_value_t = false)] pub allow_removable: bool, /// Print detection and planning summary as JSON to stdout (non-default) #[arg(long = "show", default_value_t = false)] pub show: bool, /// Write detection/planning JSON report to the given path (overrides config.report.path) #[arg(long = "report")] pub report: Option, } /// Parse CLI arguments (non-interactive; suitable for initramfs). pub fn from_args() -> Cli { Cli::parse() }