mirror of
https://git.proxmox.com/git/pve-installer
synced 2025-07-12 14:26:53 +00:00
common: simplify filesystem type serializing & Display trait impl
Implements the proper de-/serializer directly on the type and then use serde_plain::derive_display_from_serialize where applicable, instead of separate serializer functions somewhere else. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
This commit is contained in:
parent
b153d92d1f
commit
510b0c008f
@ -12,3 +12,4 @@ anyhow.workspace = true
|
|||||||
regex = "1.7"
|
regex = "1.7"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
serde_plain = "1.0"
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::{cmp, fmt};
|
use std::{cmp, fmt};
|
||||||
|
|
||||||
@ -10,55 +11,33 @@ use crate::setup::{
|
|||||||
};
|
};
|
||||||
use crate::utils::{CidrAddress, Fqdn};
|
use crate::utils::{CidrAddress, Fqdn};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all(deserialize = "lowercase", serialize = "UPPERCASE"))]
|
||||||
pub enum BtrfsRaidLevel {
|
pub enum BtrfsRaidLevel {
|
||||||
Raid0,
|
Raid0,
|
||||||
Raid1,
|
Raid1,
|
||||||
Raid10,
|
Raid10,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BtrfsRaidLevel {
|
serde_plain::derive_display_from_serialize!(BtrfsRaidLevel);
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use BtrfsRaidLevel::*;
|
|
||||||
match self {
|
|
||||||
Raid0 => write!(f, "RAID0"),
|
|
||||||
Raid1 => write!(f, "RAID1"),
|
|
||||||
Raid10 => write!(f, "RAID10"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all(deserialize = "lowercase", serialize = "UPPERCASE"))]
|
||||||
pub enum ZfsRaidLevel {
|
pub enum ZfsRaidLevel {
|
||||||
Raid0,
|
Raid0,
|
||||||
Raid1,
|
Raid1,
|
||||||
Raid10,
|
Raid10,
|
||||||
#[serde(rename = "raidz-1")]
|
#[serde(rename = "RAIDZ-1")]
|
||||||
RaidZ,
|
RaidZ,
|
||||||
#[serde(rename = "raidz-2")]
|
#[serde(rename = "RAIDZ-2")]
|
||||||
RaidZ2,
|
RaidZ2,
|
||||||
#[serde(rename = "raidz-3")]
|
#[serde(rename = "RAIDZ-3")]
|
||||||
RaidZ3,
|
RaidZ3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ZfsRaidLevel {
|
serde_plain::derive_display_from_serialize!(ZfsRaidLevel);
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use ZfsRaidLevel::*;
|
|
||||||
match self {
|
|
||||||
Raid0 => write!(f, "RAID0"),
|
|
||||||
Raid1 => write!(f, "RAID1"),
|
|
||||||
Raid10 => write!(f, "RAID10"),
|
|
||||||
RaidZ => write!(f, "RAIDZ-1"),
|
|
||||||
RaidZ2 => write!(f, "RAIDZ-2"),
|
|
||||||
RaidZ3 => write!(f, "RAIDZ-3"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
pub enum FsType {
|
pub enum FsType {
|
||||||
Ext4,
|
Ext4,
|
||||||
Xfs,
|
Xfs,
|
||||||
@ -74,16 +53,59 @@ impl FsType {
|
|||||||
|
|
||||||
impl fmt::Display for FsType {
|
impl fmt::Display for FsType {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use FsType::*;
|
// Values displayed to the user in the installer UI
|
||||||
match self {
|
match self {
|
||||||
Ext4 => write!(f, "ext4"),
|
FsType::Ext4 => write!(f, "ext4"),
|
||||||
Xfs => write!(f, "XFS"),
|
FsType::Xfs => write!(f, "XFS"),
|
||||||
Zfs(level) => write!(f, "ZFS ({level})"),
|
FsType::Zfs(level) => write!(f, "ZFS ({level})"),
|
||||||
Btrfs(level) => write!(f, "Btrfs ({level})"),
|
FsType::Btrfs(level) => write!(f, "Btrfs ({level})"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for FsType {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
// These values must match exactly what the low-level installer expects
|
||||||
|
let value = match self {
|
||||||
|
// proxinstall::$fssetup
|
||||||
|
FsType::Ext4 => "ext4",
|
||||||
|
FsType::Xfs => "xfs",
|
||||||
|
// proxinstall::get_zfs_raid_setup()
|
||||||
|
FsType::Zfs(level) => &format!("zfs ({level})"),
|
||||||
|
// proxinstall::get_btrfs_raid_setup()
|
||||||
|
FsType::Btrfs(level) => &format!("btrfs ({level})"),
|
||||||
|
};
|
||||||
|
|
||||||
|
serializer.collect_str(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for FsType {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"ext4" => Ok(FsType::Ext4),
|
||||||
|
"xfs" => Ok(FsType::Xfs),
|
||||||
|
"zfs (RAID0)" => Ok(FsType::Zfs(ZfsRaidLevel::Raid0)),
|
||||||
|
"zfs (RAID1)" => Ok(FsType::Zfs(ZfsRaidLevel::Raid1)),
|
||||||
|
"zfs (RAID10)" => Ok(FsType::Zfs(ZfsRaidLevel::Raid10)),
|
||||||
|
"zfs (RAIDZ-1)" => Ok(FsType::Zfs(ZfsRaidLevel::RaidZ)),
|
||||||
|
"zfs (RAIDZ-2)" => Ok(FsType::Zfs(ZfsRaidLevel::RaidZ2)),
|
||||||
|
"zfs (RAIDZ-3)" => Ok(FsType::Zfs(ZfsRaidLevel::RaidZ3)),
|
||||||
|
"btrfs (RAID0)" => Ok(FsType::Btrfs(BtrfsRaidLevel::Raid0)),
|
||||||
|
"btrfs (RAID1)" => Ok(FsType::Btrfs(BtrfsRaidLevel::Raid1)),
|
||||||
|
"btrfs (RAID10)" => Ok(FsType::Btrfs(BtrfsRaidLevel::Raid10)),
|
||||||
|
_ => Err(format!("Could not find file system: {s}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serde_plain::derive_deserialize_from_fromstr!(FsType, "valid filesystem");
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LvmBootdiskOptions {
|
pub struct LvmBootdiskOptions {
|
||||||
pub total_size: f64,
|
pub total_size: f64,
|
||||||
@ -122,8 +144,8 @@ impl BtrfsBootdiskOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[serde(rename_all(deserialize = "lowercase"))]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum ZfsCompressOption {
|
pub enum ZfsCompressOption {
|
||||||
#[default]
|
#[default]
|
||||||
On,
|
On,
|
||||||
@ -135,11 +157,7 @@ pub enum ZfsCompressOption {
|
|||||||
Zstd,
|
Zstd,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ZfsCompressOption {
|
serde_plain::derive_display_from_serialize!(ZfsCompressOption);
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", format!("{self:?}").to_lowercase())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&ZfsCompressOption> for String {
|
impl From<&ZfsCompressOption> for String {
|
||||||
fn from(value: &ZfsCompressOption) -> Self {
|
fn from(value: &ZfsCompressOption) -> Self {
|
||||||
@ -152,7 +170,7 @@ pub const ZFS_COMPRESS_OPTIONS: &[ZfsCompressOption] = {
|
|||||||
&[On, Off, Lzjb, Lz4, Zle, Gzip, Zstd]
|
&[On, Off, Lzjb, Lz4, Zle, Gzip, Zstd]
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum ZfsChecksumOption {
|
pub enum ZfsChecksumOption {
|
||||||
#[default]
|
#[default]
|
||||||
@ -161,11 +179,7 @@ pub enum ZfsChecksumOption {
|
|||||||
Sha256,
|
Sha256,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ZfsChecksumOption {
|
serde_plain::derive_display_from_serialize!(ZfsChecksumOption);
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", format!("{self:?}").to_lowercase())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&ZfsChecksumOption> for String {
|
impl From<&ZfsChecksumOption> for String {
|
||||||
fn from(value: &ZfsChecksumOption) -> Self {
|
fn from(value: &ZfsChecksumOption) -> Self {
|
||||||
|
@ -12,10 +12,7 @@ use std::{
|
|||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
options::{
|
options::{Disk, FsType, ZfsBootdiskOptions, ZfsChecksumOption, ZfsCompressOption},
|
||||||
BtrfsRaidLevel, Disk, FsType, ZfsBootdiskOptions, ZfsChecksumOption, ZfsCompressOption,
|
|
||||||
ZfsRaidLevel,
|
|
||||||
},
|
|
||||||
utils::CidrAddress,
|
utils::CidrAddress,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -208,9 +205,7 @@ pub fn load_installer_setup_files(
|
|||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct InstallZfsOption {
|
pub struct InstallZfsOption {
|
||||||
pub ashift: usize,
|
pub ashift: usize,
|
||||||
#[serde(serialize_with = "serialize_as_display")]
|
|
||||||
pub compress: ZfsCompressOption,
|
pub compress: ZfsCompressOption,
|
||||||
#[serde(serialize_with = "serialize_as_display")]
|
|
||||||
pub checksum: ZfsChecksumOption,
|
pub checksum: ZfsChecksumOption,
|
||||||
pub copies: usize,
|
pub copies: usize,
|
||||||
pub arc_max: usize,
|
pub arc_max: usize,
|
||||||
@ -476,10 +471,6 @@ pub fn spawn_low_level_installer(test_mode: bool) -> io::Result<process::Child>
|
|||||||
pub struct InstallConfig {
|
pub struct InstallConfig {
|
||||||
pub autoreboot: usize,
|
pub autoreboot: usize,
|
||||||
|
|
||||||
#[serde(
|
|
||||||
serialize_with = "serialize_fstype",
|
|
||||||
deserialize_with = "deserialize_fs_type"
|
|
||||||
)]
|
|
||||||
pub filesys: FsType,
|
pub filesys: FsType,
|
||||||
pub hdsize: f64,
|
pub hdsize: f64,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@ -538,51 +529,3 @@ where
|
|||||||
serializer.serialize_none()
|
serializer.serialize_none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_fstype<S>(value: &FsType, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
use FsType::*;
|
|
||||||
let value = match value {
|
|
||||||
// proxinstall::$fssetup
|
|
||||||
Ext4 => "ext4",
|
|
||||||
Xfs => "xfs",
|
|
||||||
// proxinstall::get_zfs_raid_setup()
|
|
||||||
Zfs(ZfsRaidLevel::Raid0) => "zfs (RAID0)",
|
|
||||||
Zfs(ZfsRaidLevel::Raid1) => "zfs (RAID1)",
|
|
||||||
Zfs(ZfsRaidLevel::Raid10) => "zfs (RAID10)",
|
|
||||||
Zfs(ZfsRaidLevel::RaidZ) => "zfs (RAIDZ-1)",
|
|
||||||
Zfs(ZfsRaidLevel::RaidZ2) => "zfs (RAIDZ-2)",
|
|
||||||
Zfs(ZfsRaidLevel::RaidZ3) => "zfs (RAIDZ-3)",
|
|
||||||
// proxinstall::get_btrfs_raid_setup()
|
|
||||||
Btrfs(BtrfsRaidLevel::Raid0) => "btrfs (RAID0)",
|
|
||||||
Btrfs(BtrfsRaidLevel::Raid1) => "btrfs (RAID1)",
|
|
||||||
Btrfs(BtrfsRaidLevel::Raid10) => "btrfs (RAID10)",
|
|
||||||
};
|
|
||||||
|
|
||||||
serializer.collect_str(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize_fs_type<'de, D>(deserializer: D) -> Result<FsType, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
use FsType::*;
|
|
||||||
let de_fs: String = Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
match de_fs.as_str() {
|
|
||||||
"ext4" => Ok(Ext4),
|
|
||||||
"xfs" => Ok(Xfs),
|
|
||||||
"zfs (RAID0)" => Ok(Zfs(ZfsRaidLevel::Raid0)),
|
|
||||||
"zfs (RAID1)" => Ok(Zfs(ZfsRaidLevel::Raid1)),
|
|
||||||
"zfs (RAID10)" => Ok(Zfs(ZfsRaidLevel::Raid10)),
|
|
||||||
"zfs (RAIDZ-1)" => Ok(Zfs(ZfsRaidLevel::RaidZ)),
|
|
||||||
"zfs (RAIDZ-2)" => Ok(Zfs(ZfsRaidLevel::RaidZ2)),
|
|
||||||
"zfs (RAIDZ-3)" => Ok(Zfs(ZfsRaidLevel::RaidZ3)),
|
|
||||||
"btrfs (RAID0)" => Ok(Btrfs(BtrfsRaidLevel::Raid0)),
|
|
||||||
"btrfs (RAID1)" => Ok(Btrfs(BtrfsRaidLevel::Raid1)),
|
|
||||||
"btrfs (RAID10)" => Ok(Btrfs(BtrfsRaidLevel::Raid10)),
|
|
||||||
_ => Err(de::Error::custom("could not find file system: {de_fs}")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user