runk: Support list sub-command

Support list sub-command. It will traverse the root directory, parse
status file and print basic information of containers. Behavior and
print format consistent with runc. To handle race with runk delete
or system user modify, the loop will continue to traverse when errors
are encountered.

Fixes: #4362

Signed-off-by: Chen Yiyang <cyyzero@qq.com>
This commit is contained in:
Chen Yiyang 2022-06-02 11:22:20 +08:00
parent b8e98b175c
commit 38a3188206
No known key found for this signature in database
GPG Key ID: 67736A13C4B91126
5 changed files with 100 additions and 0 deletions

View File

@ -985,7 +985,9 @@ dependencies = [
"serde_json",
"slog",
"slog-async",
"tabwriter",
"tokio",
"users",
]
[[package]]
@ -1166,6 +1168,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tabwriter"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36205cfc997faadcc4b0b87aaef3fbedafe20d38d4959a7ca6ff803564051111"
dependencies = [
"unicode-width",
]
[[package]]
name = "take_mut"
version = "0.2.2"
@ -1348,12 +1359,28 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "users"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
dependencies = [
"libc",
"log",
]
[[package]]
name = "version_check"
version = "0.9.4"

View File

@ -22,6 +22,8 @@ slog-async = "2.7.0"
tokio = { version = "1.15.0", features = ["full"] }
serde = { version = "1.0.133", features = ["derive"] }
serde_json = "1.0.74"
users = "0.11.0"
tabwriter = "1.2.1"
[workspace]
members = [

View File

@ -0,0 +1,69 @@
// Copyright 2021-2022 Kata Contributors
//
// SPDX-License-Identifier: Apache-2.0
//
use super::state::get_container_state_name;
use anyhow::Result;
use libcontainer::status::{get_current_container_state, Status};
use liboci_cli::List;
use oci::ContainerState;
use slog::{info, Logger};
use std::{fs, os::unix::prelude::MetadataExt, path::Path};
use std::{io, io::Write};
use tabwriter::TabWriter;
use users::get_user_by_uid;
pub fn run(_: List, root: &Path, logger: &Logger) -> Result<()> {
let mut content = String::new();
for entry in fs::read_dir(root)? {
let entry = entry?;
// Possibly race with runk delete, so continue loop when any error occurs below
let metadata = match entry.metadata() {
Ok(metadata) => metadata,
Err(_) => continue,
};
if !metadata.is_dir() {
continue;
}
let container_id = match entry.file_name().into_string() {
Ok(id) => id,
Err(_) => continue,
};
let status = match Status::load(root, &container_id) {
Ok(status) => status,
Err(_) => continue,
};
let state = match get_current_container_state(&status) {
Ok(state) => state,
Err(_) => continue,
};
// Just like runc, pid of stopped container is 0
let pid = match state {
ContainerState::Stopped => 0,
_ => status.pid,
};
// May replace get_user_by_uid with getpwuid(3)
let owner = match get_user_by_uid(metadata.uid()) {
Some(user) => String::from(user.name().to_string_lossy()),
None => format!("#{}", metadata.uid()),
};
content.push_str(&format!(
"{}\t{}\t{}\t{}\t{}\t{}\n",
container_id,
pid,
get_container_state_name(state),
status.bundle.display(),
status.created,
owner
));
}
let mut tab_writer = TabWriter::new(io::stdout());
writeln!(&mut tab_writer, "ID\tPID\tSTATUS\tBUNDLE\tCREATED\tOWNER")?;
write!(&mut tab_writer, "{}", content)?;
tab_writer.flush()?;
info!(&logger, "list command finished successfully");
Ok(())
}

View File

@ -6,6 +6,7 @@
pub mod create;
pub mod delete;
pub mod kill;
pub mod list;
pub mod run;
pub mod spec;
pub mod start;

View File

@ -78,6 +78,7 @@ async fn cmd_run(subcmd: SubCommand, root_path: &Path, logger: &Logger) -> Resul
SubCommand::Common(cmd) => match cmd {
CommonCmd::Run(run) => commands::run::run(run, root_path, logger).await,
CommonCmd::Spec(spec) => commands::spec::run(spec, logger),
CommonCmd::List(list) => commands::list::run(list, root_path, logger),
_ => {
return Err(anyhow!("command is not implemented yet"));
}