use std::{
error::Error,
fs::create_dir_all,
io,
os::unix::fs::symlink,
path::{Path, PathBuf},
};
use log::{error, warn};
use uuid::Uuid;
use super::lib;
const WANTED_BY_INITRD_PATH: &str = "/run/systemd/system/initrd.target.wants";
fn make_wanted_by_initrd(unit_path: &Path) -> Result<(), io::Error> {
let initrd_target_wants_path = &Path::new(WANTED_BY_INITRD_PATH);
if !initrd_target_wants_path.exists() {
create_dir_all(initrd_target_wants_path)?;
}
symlink(
unit_path,
[
initrd_target_wants_path,
&Path::new(unit_path.file_name().expect("Is unit file")),
]
.iter()
.collect::<PathBuf>(),
)?;
Ok(())
}
fn unit_template(pool_uuid: Uuid) -> String {
format!(
r"[Unit]
Description=setup for Stratis root filesystem
DefaultDependencies=no
Conflicts=shutdown.target
OnFailure=emergency.target
OnFailureJobMode=isolate
Wants=stratisd-min.service plymouth-start.service stratis-clevis-setup.service
After=paths.target plymouth-start.service stratisd-min.service
Before=initrd.target
[Service]
Type=oneshot
Environment='STRATIS_ROOTFS_UUID={}'
ExecStart=/usr/lib/systemd/stratis-rootfs-setup
RemainAfterExit=yes
",
pool_uuid,
)
}
fn generator_with_err(early_dir: String) -> Result<(), Box<dyn Error>> {
let kernel_cmdline = lib::get_kernel_cmdline()?;
let pool_uuid_key = "stratis.rootfs.pool_uuid";
let pool_uuid = match kernel_cmdline
.get(pool_uuid_key)
.and_then(|opt_vec| opt_vec.as_ref())
.and_then(|vec| vec.iter().next())
{
Some(uuid) => uuid,
None => {
warn!(
"{} kernel command line parameter not found; disabling generator",
pool_uuid_key
);
return Ok(());
}
};
let parsed_pool_uuid = Uuid::parse_str(&pool_uuid)?;
let file_contents = unit_template(parsed_pool_uuid);
let mut path = PathBuf::from(early_dir);
path.push("stratis-setup.service");
lib::write_unit_file(&path, file_contents)?;
make_wanted_by_initrd(&path)?;
Ok(())
}
pub fn generator(early_dir: String) -> Result<(), Box<dyn Error>> {
lib::setup_logger()?;
let res = generator_with_err(early_dir);
if let Err(ref e) = res {
error!("systemd generator failed with error: {}", e);
}
res
}