mirror of
https://github.com/containers/youki
synced 2024-09-20 02:41:47 +02:00
Merge branch 'utam0k:main' into main
This commit is contained in:
commit
f37079b56f
@ -3,6 +3,7 @@ name = "youki"
|
||||
version = "0.0.1"
|
||||
authors = ["utam0k <k0ma@utam0k.jp>"]
|
||||
edition = "2018"
|
||||
description = "A container runtime written in Rust"
|
||||
|
||||
[dependencies]
|
||||
clap = "3.0.0-beta.2"
|
||||
|
53
docs/doc-draft.md
Normal file
53
docs/doc-draft.md
Normal file
@ -0,0 +1,53 @@
|
||||
_This is a draft for a high level documentation of Youki. After finished this is intended to provide how control flow and high level functioning of Youki happens for development purposes._
|
||||
|
||||
## Some reference links
|
||||
|
||||
These are references to various documentations and specifications, which can be useful to understand commands and constraints.
|
||||
|
||||
- [OCI runtime specification] : The specification for a container runtime. Any OCI complaisant runtime must follow this.
|
||||
- [runc man pages] : has information on various commandline options supported by runc, can be used to understand commands and their options.
|
||||
- [cgroups man page](https://man7.org/linux/man-pages/man7/cgroups.7.html) : contains information about cgroups, their creation, deletion etc.
|
||||
|
||||
---
|
||||
|
||||
## Control flow diagram
|
||||
|
||||
This is diagram as given in #14, which is not actually how this works, but helpful to understand overall flow. Someone needs to check and correct.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant D as Docker
|
||||
participant YP as Youki(Parent Process)
|
||||
participant YC as Youki(Child Process)
|
||||
participant YI as Youki(Init Process)
|
||||
|
||||
|
||||
U ->> D : $ docker run --rm -it --runtime youki $image
|
||||
D ->> YP : youki create $container_id
|
||||
YP ->> YC : fork(2)
|
||||
YC ->> YC : create new namespace
|
||||
YC ->> YI : fork(2)
|
||||
YI ->> YI : Mount the device
|
||||
YI -->> YP : ready message (Unix domain socket)
|
||||
YP ->> D : exit $code
|
||||
D ->> YP : $ youki start $container_id
|
||||
YP -->> YI : start message (Unix domain socket)
|
||||
YI ->> YI : run the commands in dockerfile
|
||||
D ->> D : monitor pid written in pid file
|
||||
D ->> U : exit $code
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Control flow
|
||||
|
||||
### main invocation
|
||||
|
||||
On invoking Youki, main function parses args passed to it, which contains directory path to store container state (check runc . 8 . md in [runc man pages]), optional log path and log format string and a subcommand such as create, delete etc.
|
||||
|
||||
From there it matches subcommand arg with possible subcommand and takes appropriate actions, such as creating a new container, deleting a container erc.
|
||||
|
||||
[oci runtime specification]: https://github.com/opencontainers/runtime-spec/blob/master/runtime.md
|
||||
[runc man pages]: (https://github.com/opencontainers/runc/blob/master/man/runc.8.md)
|
28
src/main.rs
28
src/main.rs
@ -1,3 +1,7 @@
|
||||
//! # Youki
|
||||
//! Container Runtime written in Rust, inspired by [railcar](https://github.com/oracle/railcar)
|
||||
//! This crate provides a container runtime which can be used by a high-level container runtime to run containers.
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -12,15 +16,20 @@ use youki::spec;
|
||||
use youki::start;
|
||||
use youki::{cgroups::Manager, command::linux::LinuxCommand};
|
||||
|
||||
/// High-level commandline option definition
|
||||
/// This takes global options as well as individual commands as specified in [OCI runtime-spec](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md)
|
||||
/// Also check [runc commandline documentation](https://github.com/opencontainers/runc/blob/master/man/runc.8.md) for more explanation
|
||||
#[derive(Clap, Debug)]
|
||||
#[clap(version = "1.0", author = "utam0k <k0ma@utam0k.jp>")]
|
||||
struct Opts {
|
||||
/// root directory to store container state
|
||||
#[clap(short, long, default_value = "/run/youki")]
|
||||
root: PathBuf,
|
||||
#[clap(short, long)]
|
||||
log: Option<PathBuf>,
|
||||
#[clap(long)]
|
||||
log_format: Option<String>,
|
||||
/// command to actually manage container
|
||||
#[clap(subcommand)]
|
||||
subcmd: SubCommand,
|
||||
}
|
||||
@ -40,6 +49,9 @@ pub struct Delete {
|
||||
pub struct StateArgs {
|
||||
pub container_id: String,
|
||||
}
|
||||
|
||||
/// Subcommands accepted by Youki, confirming with [OCI runtime-spec](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md)
|
||||
/// Also for a short information, check [runc commandline documentation](https://github.com/opencontainers/runc/blob/master/man/runc.8.md)
|
||||
#[derive(Clap, Debug)]
|
||||
enum SubCommand {
|
||||
#[clap(version = "0.0.1", author = "utam0k <k0ma@utam0k.jp>")]
|
||||
@ -66,6 +78,8 @@ impl SubCommand {
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the entry point in the container runtime. The binary is run by a high-level container runtime,
|
||||
/// with various flags passed. This parses the flags, creates and manages appropriate resources.
|
||||
fn main() -> Result<()> {
|
||||
let opts = Opts::parse();
|
||||
|
||||
@ -88,11 +102,17 @@ fn main() -> Result<()> {
|
||||
SubCommand::Create(create) => create.exec(root_path, LinuxCommand),
|
||||
SubCommand::Start(start) => start.exec(root_path),
|
||||
SubCommand::Kill(kill) => {
|
||||
// resolves relative paths, symbolic links etc. and get complete path
|
||||
let root_path = fs::canonicalize(root_path)?;
|
||||
// state of container is stored in a directory named as container id inside
|
||||
// root directory given in commandline options
|
||||
let container_root = root_path.join(&kill.container_id);
|
||||
if !container_root.exists() {
|
||||
bail!("{} doesn't exists.", kill.container_id)
|
||||
}
|
||||
|
||||
// load container state from json file, and check status of the container
|
||||
// it might be possible that kill is invoked on a already stopped container etc.
|
||||
let container = Container::load(container_root)?.refresh_status()?;
|
||||
if container.can_kill() {
|
||||
let sig = signal::from_str(kill.signal.as_str())?;
|
||||
@ -109,15 +129,23 @@ fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
SubCommand::Delete(delete) => {
|
||||
// state of container is stored in a directory named as container id inside
|
||||
// root directory given in commandline options
|
||||
let container_root = root_path.join(&delete.container_id);
|
||||
if !container_root.exists() {
|
||||
bail!("{} doesn't exists.", delete.container_id)
|
||||
}
|
||||
// load container state from json file, and check status of the container
|
||||
// it might be possible that delete is invoked on a running container.
|
||||
let container = Container::load(container_root)?.refresh_status()?;
|
||||
if container.can_delete() {
|
||||
if container.root.exists() {
|
||||
// remove the directory storing container state
|
||||
fs::remove_dir_all(&container.root)?;
|
||||
let spec = spec::Spec::load("config.json")?;
|
||||
// remove the cgroup created for the container
|
||||
// check https://man7.org/linux/man-pages/man7/cgroups.7.html
|
||||
// creating and removing cgroups section for more information on cgroups
|
||||
let cmanager = Manager::new(spec.linux.unwrap().cgroups_path)?;
|
||||
cmanager.remove()?;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user