isoloom_spec/model/
virtiofs.rs1use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7pub const MAX_VIRTIOFS: usize = 8;
9
10#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
16#[serde(deny_unknown_fields)]
17pub struct Virtiofs {
18 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub mapping: Option<String>,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub cache: Option<VirtiofsCache>,
28 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
31 pub direct_io: bool,
32 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
34 pub xattr: bool,
35 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
37 pub acl: bool,
38}
39
40#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
42#[serde(rename_all = "lowercase")]
43pub enum VirtiofsCache {
44 #[default]
46 Auto,
47 Always,
49 Metadata,
51 Never,
53}
54
55impl VirtiofsCache {
56 #[must_use]
58 pub fn id(self) -> &'static str {
59 match self {
60 VirtiofsCache::Auto => "auto",
61 VirtiofsCache::Always => "always",
62 VirtiofsCache::Metadata => "metadata",
63 VirtiofsCache::Never => "never",
64 }
65 }
66}
67
68impl Virtiofs {
69 #[must_use]
71 pub fn exposes_xattr(&self) -> bool {
72 self.xattr || self.acl
73 }
74}
75
76#[must_use]
79pub fn mapping_id(id: &str) -> bool {
80 id.len() <= 64 && id.starts_with(|c: char| c.is_ascii_alphabetic()) && id.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '-' | '_'))
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn a_cache_goes_by_the_name_proxmox_takes() -> Result<(), serde_yaml_ng::Error> {
89 for cache in [VirtiofsCache::Auto, VirtiofsCache::Always, VirtiofsCache::Metadata, VirtiofsCache::Never] {
90 assert_eq!(serde_yaml_ng::from_str::<VirtiofsCache>(cache.id())?, cache);
91 }
92 Ok(())
93 }
94
95 #[test]
96 fn extended_attributes_pass_when_asked_for_or_acls_need_them() -> Result<(), serde_yaml_ng::Error> {
97 let mut read = Vec::new();
98 for yaml in ["{}", "{ xattr: true }", "{ acl: true }"] {
99 read.push(serde_yaml_ng::from_str::<Virtiofs>(yaml)?.exposes_xattr());
100 }
101 assert_eq!(read, [false, true, true]);
102 Ok(())
103 }
104
105 #[test]
106 fn a_mapping_id_is_a_letter_then_up_to_63_letters_digits_dashes_or_underscores() {
107 let longest = format!("a{}", "b".repeat(63));
108 let ids = ["share-1_a", longest.as_str(), &format!("{longest}c"), "1share", "a b", "a.b"];
109 assert_eq!(ids.map(mapping_id), [true, true, false, false, false, false]);
110 }
111}