in sources/api/host-containers/src/main.rs [361:451]
fn handle_host_container<S>(name: S, image_details: &model::HostContainer) -> Result<()>
where
S: AsRef<str>,
{
// Get basic settings, as retrieved from API.
let name = name.as_ref();
let source = image_details.source.as_ref().context(error::MissingField {
name,
field: "source",
})?;
let enabled = image_details.enabled.unwrap_or(false);
let superpowered = image_details.superpowered.unwrap_or(false);
info!(
"Host container '{}' is enabled: {}, superpowered: {}, with source: {}",
name, enabled, superpowered, source
);
// Create the directory regardless if user data was provided for the container
let dir = Path::new(PERSISTENT_STORAGE_BASE_DIR).join(name);
fs::create_dir_all(&dir).context(error::Mkdir { dir: &dir })?;
fs::set_permissions(&dir, fs::Permissions::from_mode(0o700))
.context(error::SetPermissions { name })?;
// If user data was specified, unencode it and write it out before we start the container.
if let Some(user_data) = &image_details.user_data {
let decoded_bytes =
base64::decode(user_data.as_bytes()).context(error::Base64Decode { name })?;
let path = dir.join("user-data");
fs::write(path, decoded_bytes).context(error::UserDataWrite { name })?;
}
// Write the environment file needed for the systemd service to have details about this
// specific host container
write_env_file(name, source, enabled, superpowered)?;
// Now start/stop the container according to the 'enabled' setting
let unit_name = format!("host-containers@{}.service", name);
let systemd_unit = SystemdUnit::new(&unit_name);
let host_containerd_unit = SystemdUnit::new("host-containerd.service");
if enabled {
// If this particular host-container was previously disabled. Let's make sure there's no
// lingering container tasks left over previously that host-ctr might bind to.
// We want to ensure we're running the host-container with the latest configuration.
//
// We only attempt to do this only if host-containerd is active and running
if host_containerd_unit.is_active()? && !systemd_unit.is_enabled()? {
command(
constants::HOST_CTR_BIN,
&["clean-up", "--container-id", name],
)?;
}
// Only start the host container if the systemd target is 'multi-user', otherwise
// it will start before the system is fully configured
match command(constants::SYSTEMCTL_BIN, &["get-default"])?
.trim()
.as_ref()
{
"multi-user.target" => {
if systemd_unit.is_active()? {
debug!("Stopping and starting host container: '{}'", unit_name);
systemd_unit.try_reload_or_restart()?
} else {
debug!("Enabling and starting container: '{}'", unit_name);
systemd_unit.enable_and_start()?
}
}
_ => {
debug!("Enabling: '{}'", unit_name);
systemd_unit.enable()?
}
};
} else {
systemd_unit.disable_and_stop()?;
// Ensure there's no lingering host-container after it's been disabled.
//
// We only attempt to do this only if host-containerd is active and running
if host_containerd_unit.is_active()? {
command(
constants::HOST_CTR_BIN,
&["clean-up", "--container-id", name],
)?;
}
}
Ok(())
}