aboutsummaryrefslogtreecommitdiffstats
path: root/zone_zfs/src/zfs.rs
blob: 7f349515c06981dd05fd05feda4ba12be7a96685 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use figment::{Figment, Provider};
use std::path::PathBuf;
use std::process::Command;

use crate::{Config, Error, FileSystem, Result};

#[derive(Default, Debug)]
pub struct ZFS {
    pub config: Config,
}

impl ZFS {
    pub fn new() -> Result<Self> {
        Self::custom(Config::figment())
    }

    pub fn custom<T: Provider>(provider: T) -> Result<Self> {
        Config::from(Figment::from(provider))
            .map_err(Error::from)
            .map(|config| Self { config })
    }

    pub fn clone_from_latest(&self, name: PathBuf, parent: PathBuf) -> Result<FileSystem> {
        Self::get_file_system(parent)?
            .get_latest_snapshot()?
            .ok_or_else(|| Error::Snapshot("No snapshot found".into()))?
            .clone_into_file_system(name)?
            .set_quota(self.config.quota)
    }

    pub(super) fn get_file_systems() -> Result<Vec<FileSystem>> {
        Command::new("zfs")
            .arg("list")
            .arg("-H")
            .arg("-o")
            .arg("name")
            .output()
            .map(|o| String::from_utf8(o.stdout))?
            .map_err(|err| Error::FileSystem(format!("Failed to parse command output: {:?}", err)))?
            .split_whitespace()
            .map(FileSystem::try_from)
            .collect()
    }

    fn get_file_system(name: PathBuf) -> Result<FileSystem> {
        Self::get_file_systems()?
            .into_iter()
            .find(|fs| PathBuf::from(&fs.value).ends_with(&name))
            .ok_or_else(|| Error::FileSystem("No file system found".into()))
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn zfs_list() {
        use super::*;
        assert!(ZFS::get_file_systems().is_ok());
    }
}