aprender-zram-generator 0.34.0

systemd generator for zram device configuration
//! systemd unit file generation.

use crate::config::{Config, ZramConfig};
use std::fs;
use std::path::Path;

/// Generate systemd units for zram configuration.
pub fn generate_units(output_dir: &str, config: &Config) -> Result<(), Box<dyn std::error::Error>> {
    let output_path = Path::new(output_dir);
    fs::create_dir_all(output_path)?;

    for device_config in &config.devices {
        generate_device_unit(output_path, device_config)?;
        generate_swap_unit(output_path, device_config)?;
    }

    Ok(())
}

fn generate_device_unit(
    output_dir: &Path,
    config: &ZramConfig,
) -> Result<(), Box<dyn std::error::Error>> {
    let unit_name = format!("trueno-zram{}.service", config.device);
    let unit_path = output_dir.join(&unit_name);

    let unit_content = format!(
        r"# Generated by trueno-zram-generator
[Unit]
Description=Configure zram device {device}
DefaultDependencies=no
After=local-fs.target
Before=swap.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/trueno-zram create --device {device} --size {size} --algorithm {algorithm} --streams {streams}
ExecStop=/usr/bin/trueno-zram remove --device {device}

[Install]
WantedBy=swap.target
",
        device = config.device,
        size = config.size,
        algorithm = config.algorithm,
        streams = config.streams,
    );

    fs::write(unit_path, unit_content)?;
    Ok(())
}

fn generate_swap_unit(
    output_dir: &Path,
    config: &ZramConfig,
) -> Result<(), Box<dyn std::error::Error>> {
    let unit_name = format!("dev-zram{}.swap", config.device);
    let unit_path = output_dir.join(&unit_name);

    let unit_content = format!(
        r"# Generated by trueno-zram-generator
[Unit]
Description=Compressed swap on zram{device}
Requires=trueno-zram{device}.service
After=trueno-zram{device}.service

[Swap]
What=/dev/zram{device}
Priority={priority}

[Install]
WantedBy=swap.target
",
        device = config.device,
        priority = config.priority,
    );

    fs::write(unit_path, unit_content)?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;

    #[test]
    fn test_generate_units() {
        let temp_dir = std::env::temp_dir().join("trueno-zram-test");
        let _ = fs::remove_dir_all(&temp_dir);
        fs::create_dir_all(&temp_dir).unwrap();

        let config = Config {
            devices: vec![ZramConfig {
                device: 0,
                size: "4G".to_string(),
                algorithm: "lz4".to_string(),
                streams: 4,
                priority: 100,
            }],
        };

        generate_units(temp_dir.to_str().unwrap(), &config).unwrap();

        assert!(temp_dir.join("trueno-zram0.service").exists());
        assert!(temp_dir.join("dev-zram0.swap").exists());

        let _ = fs::remove_dir_all(&temp_dir);
    }
}