-
Notifications
You must be signed in to change notification settings - Fork 346
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds the first code to checkpoint a container. The checkpoint command is name 'checkpointt' (with two 't's at the end) so that container engines like Podman do not think to use this not yet finished checkpoint restore implementation. For Podman it is still necessary to tell CRIU that the network namespace is external at least and restoring needs special handling to support '--console-socket'. This currently uses the not officially released CRIU Rust bindings. Signed-off-by: Adrian Reber <areber@redhat.com>
- Loading branch information
1 parent
03bbfd8
commit 5c4fca1
Showing
10 changed files
with
201 additions
and
2 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use super::{Container, ContainerStatus}; | ||
use crate::container::container::CheckpointOptions; | ||
use anyhow::{bail, Context, Result}; | ||
|
||
use oci_spec::runtime::Spec; | ||
use std::os::unix::io::AsRawFd; | ||
|
||
const CRIU_CHECKPOINT_LOG_FILE: &str = "dump.log"; | ||
|
||
impl Container { | ||
pub fn checkpoint(&mut self, opts: &CheckpointOptions) -> Result<()> { | ||
self.refresh_status() | ||
.context("failed to refresh container status")?; | ||
|
||
// can_pause() checks if the container is running. That also works for | ||
// checkpoitning. is_running() would make more sense here, but let's | ||
// just reuse existing functions. | ||
if !self.can_pause() { | ||
bail!( | ||
"{} could not be checkpointed because it was {:?}", | ||
self.id(), | ||
self.status() | ||
); | ||
} | ||
|
||
let mut criu = rust_criu::Criu::new().unwrap(); | ||
|
||
// We need to tell CRIU that all bind mounts are external. CRIU will fail checkpointing | ||
// if it does not know that these bind mounts are coming from the outside of the container. | ||
// This information is needed during restore again. The external location of the bind | ||
// mounts can change and CRIU will just mount whatever we tell it to mount based on | ||
// information found in 'config.json'. | ||
let source_spec_path = self.bundle().join("config.json"); | ||
let spec = Spec::load(&source_spec_path)?; | ||
let mounts = spec.mounts().clone(); | ||
for m in mounts.unwrap() { | ||
if m.typ() == &Some("bind".to_string()) { | ||
let dest = m | ||
.destination() | ||
.clone() | ||
.into_os_string() | ||
.into_string() | ||
.unwrap(); | ||
criu.set_external_mount(dest.clone(), dest); | ||
} | ||
} | ||
|
||
let directory = std::fs::File::open(&opts.image_path)?; | ||
criu.set_images_dir_fd(directory.as_raw_fd()); | ||
|
||
// It seems to be necessary to be defined outside of 'if' to | ||
// keep the FD open until CRIU uses it. | ||
let work_dir: std::fs::File; | ||
if let Some(wp) = &opts.work_path { | ||
work_dir = std::fs::File::open(wp)?; | ||
criu.set_work_dir_fd(work_dir.as_raw_fd()); | ||
} | ||
|
||
criu.set_log_file(CRIU_CHECKPOINT_LOG_FILE.to_string()); | ||
criu.set_log_level(4); | ||
criu.set_pid(self.pid().unwrap().into()); | ||
criu.set_leave_running(opts.leave_running); | ||
criu.set_ext_unix_sk(opts.ext_unix_sk); | ||
criu.set_shell_job(opts.shell_job); | ||
criu.set_tcp_established(opts.tcp_established); | ||
criu.set_file_locks(opts.file_locks); | ||
criu.set_orphan_pts_master(true); | ||
criu.set_manage_cgroups(true); | ||
if let Err(e) = criu.dump() { | ||
bail!( | ||
"Checkpointing container {} failed with {:?}. Please check CRIU logfile {:?}/{}", | ||
self.id(), | ||
e, | ||
match &opts.work_path { | ||
Some(wp) => wp, | ||
_ => &opts.image_path, | ||
}, | ||
CRIU_CHECKPOINT_LOG_FILE | ||
); | ||
} | ||
|
||
if !opts.leave_running { | ||
self.set_status(ContainerStatus::Stopped).save()?; | ||
} | ||
|
||
log::debug!("container {} checkpointed", self.id()); | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use clap::Parser; | ||
use std::path::PathBuf; | ||
|
||
/// Checkpoint a running container | ||
#[derive(Parser, Debug)] | ||
pub struct Checkpoint { | ||
#[clap(forbid_empty_values = true, required = true)] | ||
pub container_id: String, | ||
/// allow external unix sockets | ||
#[clap(long)] | ||
pub ext_unix_sk: bool, | ||
/// allow file locks | ||
#[clap(long)] | ||
pub file_locks: bool, | ||
/// path for saving criu image files | ||
#[clap(long, default_value = "checkpoint")] | ||
pub image_path: PathBuf, | ||
/// leave the process running after checkpointing | ||
#[clap(long)] | ||
pub leave_running: bool, | ||
/// allow shell jobs | ||
#[clap(long)] | ||
pub shell_job: bool, | ||
/// allow open tcp connections | ||
#[clap(long)] | ||
pub tcp_established: bool, | ||
/// path for saving work files and logs | ||
#[clap(long)] | ||
pub work_path: Option<PathBuf>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
//! Contains functionality of pause container command | ||
use crate::commands::load_container; | ||
use std::path::PathBuf; | ||
|
||
use anyhow::{Context, Result}; | ||
|
||
use liboci_cli::Checkpoint; | ||
|
||
pub fn checkpoint(args: Checkpoint, root_path: PathBuf) -> Result<()> { | ||
log::debug!("start checkpointing container {}", args.container_id); | ||
let mut container = load_container(root_path, &args.container_id)?; | ||
let opts = libcontainer::container::CheckpointOptions { | ||
ext_unix_sk: args.ext_unix_sk, | ||
file_locks: args.file_locks, | ||
image_path: args.image_path, | ||
leave_running: args.leave_running, | ||
shell_job: args.shell_job, | ||
tcp_established: args.tcp_established, | ||
work_path: args.work_path, | ||
}; | ||
container | ||
.checkpoint(&opts) | ||
.with_context(|| format!("failed to checkpoint container {}", args.container_id)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters