|
|
|
@ -93,13 +93,6 @@ struct RockerArgs {
|
|
|
|
cgroup: Option<String>,
|
|
|
|
cgroup: Option<String>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
macro_rules! rocker_println {
|
|
|
|
|
|
|
|
($($arg:tt)*) => {
|
|
|
|
|
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
|
|
|
|
println!($($arg)*);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// 从images解压到volumes
|
|
|
|
/// 从images解压到volumes
|
|
|
|
fn extend_image(image_name: &String) -> Result<PathBuf> {
|
|
|
|
fn extend_image(image_name: &String) -> Result<PathBuf> {
|
|
|
|
@ -217,11 +210,13 @@ fn init_container_custom_volume<P: AsRef<Path>>(container_merged_path: P, custom
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn clear_env() {
|
|
|
|
fn get_env_vec(env: &String) -> Result<Vec<String>> {
|
|
|
|
|
|
|
|
for (k, _) in std::env::vars(){
|
|
|
|
for (k, _) in std::env::vars(){
|
|
|
|
std::env::remove_var(k);
|
|
|
|
std::env::remove_var(k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn get_env_vec(env: &String) -> Result<Vec<String>> {
|
|
|
|
let env_vec = if env.starts_with("./") || env.starts_with("/") {
|
|
|
|
let env_vec = if env.starts_with("./") || env.starts_with("/") {
|
|
|
|
// 读取出路径指定的文件作为env
|
|
|
|
// 读取出路径指定的文件作为env
|
|
|
|
let env_text = fs::read_to_string(env)?;
|
|
|
|
let env_text = fs::read_to_string(env)?;
|
|
|
|
@ -301,7 +296,7 @@ fn init_container_pts() -> Result<()> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn init_container_log() -> Result<()> {
|
|
|
|
fn init_container_log() -> Result<()> {
|
|
|
|
let log_path = Path::new("logs");
|
|
|
|
let log_path = Path::new("/logs");
|
|
|
|
let log_file = fs::OpenOptions::new()
|
|
|
|
let log_file = fs::OpenOptions::new()
|
|
|
|
.append(true)
|
|
|
|
.append(true)
|
|
|
|
.write(true)
|
|
|
|
.write(true)
|
|
|
|
@ -362,15 +357,11 @@ fn create_pause(container_root_pause_path: &Path) -> Result<()> {
|
|
|
|
fn start(container_info: &ContainerInfo, cb: CloneCb, clong_flags: CloneFlags, container_merged_pause_path: &PathBuf) -> Result<()>{
|
|
|
|
fn start(container_info: &ContainerInfo, cb: CloneCb, clong_flags: CloneFlags, container_merged_pause_path: &PathBuf) -> Result<()>{
|
|
|
|
match unsafe {clone(cb, STACK.as_mut_slice(), clong_flags, None)} {
|
|
|
|
match unsafe {clone(cb, STACK.as_mut_slice(), clong_flags, None)} {
|
|
|
|
Ok(child_pid) => {
|
|
|
|
Ok(child_pid) => {
|
|
|
|
{ // 执行成功就保存吧~
|
|
|
|
|
|
|
|
let mut _container_info = container_info.clone();
|
|
|
|
|
|
|
|
_container_info.pid = child_pid.as_raw();
|
|
|
|
|
|
|
|
let _ = _container_info.flush();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// exec之前的步骤
|
|
|
|
// exec之前的步骤
|
|
|
|
create_network(&container_info.id, child_pid.as_raw());
|
|
|
|
create_network(&container_info.id, child_pid.as_raw());
|
|
|
|
Cgroup::create(&container_info.id, child_pid.as_raw(), CgroupLevel::from(container_info.cgroup_level.as_str()))?;
|
|
|
|
if let Err(e) = Cgroup::create(&container_info.id, child_pid.as_raw(), CgroupLevel::from(container_info.cgroup_level.as_str())) {
|
|
|
|
|
|
|
|
println!("cgroup create error: {}", e)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 删除 pause标志文件, 解开阻塞, 使其执行exec
|
|
|
|
// 删除 pause标志文件, 解开阻塞, 使其执行exec
|
|
|
|
(0..100).any(|i| {
|
|
|
|
(0..100).any(|i| {
|
|
|
|
@ -427,6 +418,8 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
return Err(RockerError::OtherError("容器工作目录创建失败".to_string()));
|
|
|
|
return Err(RockerError::OtherError("容器工作目录创建失败".to_string()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 保存容器信息
|
|
|
|
|
|
|
|
let _ = container_info.flush();
|
|
|
|
|
|
|
|
|
|
|
|
let rocker_user_info = User::from_name(USER_NAME)?.ok_or(RockerError::OtherError(format!("没找到 用户: {USER_NAME}")))?;
|
|
|
|
let rocker_user_info = User::from_name(USER_NAME)?.ok_or(RockerError::OtherError(format!("没找到 用户: {USER_NAME}")))?;
|
|
|
|
let rocker_uid = rocker_user_info.uid;
|
|
|
|
let rocker_uid = rocker_user_info.uid;
|
|
|
|
@ -434,7 +427,8 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -
|
|
|
|
|
|
|
|
|
|
|
|
let _cb = if let Some(exec_cmd) = is_exec_cmd {
|
|
|
|
let _cb = if let Some(exec_cmd) = is_exec_cmd {
|
|
|
|
let _cb = || {
|
|
|
|
let _cb = || {
|
|
|
|
init_exec_ns(container_info.pid).unwrap();
|
|
|
|
init_exec_ns(container_info.procs[0]).unwrap();
|
|
|
|
|
|
|
|
clear_env();
|
|
|
|
let env_vec = get_env_vec(&Default::default()).unwrap();
|
|
|
|
let env_vec = get_env_vec(&Default::default()).unwrap();
|
|
|
|
if container_info.root == false {
|
|
|
|
if container_info.root == false {
|
|
|
|
init_container_user(rocker_uid, rocker_gid).unwrap();
|
|
|
|
init_container_user(rocker_uid, rocker_gid).unwrap();
|
|
|
|
@ -458,6 +452,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
let _cb = || {
|
|
|
|
let _cb = || {
|
|
|
|
sethostname(USER_NAME).unwrap();
|
|
|
|
sethostname(USER_NAME).unwrap();
|
|
|
|
|
|
|
|
clear_env();
|
|
|
|
let env_vec = get_env_vec(&container_info.env).unwrap();
|
|
|
|
let env_vec = get_env_vec(&container_info.env).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let volume_path = extend_image(&container_info.image).unwrap();
|
|
|
|
let volume_path = extend_image(&container_info.image).unwrap();
|
|
|
|
@ -479,7 +474,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -
|
|
|
|
// 挂载proc
|
|
|
|
// 挂载proc
|
|
|
|
init_container_proc().unwrap();
|
|
|
|
init_container_proc().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// 设置自定义env
|
|
|
|
init_container_env(env_vec).unwrap();
|
|
|
|
init_container_env(env_vec).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
@ -535,7 +530,6 @@ impl Display for ContainerStatus {
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
|
|
|
struct ContainerInfo {
|
|
|
|
struct ContainerInfo {
|
|
|
|
id: String,
|
|
|
|
id: String,
|
|
|
|
pid: i32,
|
|
|
|
|
|
|
|
status: ContainerStatus,
|
|
|
|
status: ContainerStatus,
|
|
|
|
|
|
|
|
|
|
|
|
run: String, // /bin/bash
|
|
|
|
run: String, // /bin/bash
|
|
|
|
@ -545,8 +539,9 @@ struct ContainerInfo {
|
|
|
|
log: bool,
|
|
|
|
log: bool,
|
|
|
|
wait: bool,
|
|
|
|
wait: bool,
|
|
|
|
root: bool,
|
|
|
|
root: bool,
|
|
|
|
|
|
|
|
|
|
|
|
cgroup_level: String, // one/two/three
|
|
|
|
cgroup_level: String, // v1/v2/v3...
|
|
|
|
|
|
|
|
procs: Vec<i32> // 动态从控制组中获取的
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ContainerInfo {
|
|
|
|
impl ContainerInfo {
|
|
|
|
@ -564,7 +559,7 @@ impl Display for ContainerInfo {
|
|
|
|
let env: String = self.env.chars().take(20).collect();
|
|
|
|
let env: String = self.env.chars().take(20).collect();
|
|
|
|
let run: String = self.run.chars().take(20).collect();
|
|
|
|
let run: String = self.run.chars().take(20).collect();
|
|
|
|
let image: String = self.image.chars().take(10).collect();
|
|
|
|
let image: String = self.image.chars().take(10).collect();
|
|
|
|
write!(f, "\x1b[4m{:<10} {:<8} {:<10} {:<20} {:<20} {:<20} {:<10}\x1b[24m", self.id, self.pid, image, run, volume, env, &self.status)
|
|
|
|
write!(f, "\x1b[4m{:<10} {:<10} {:<20} {:<20} {:<20} {:<10}\x1b[24m", self.id, image, run, volume, env, &self.status)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -575,18 +570,10 @@ fn get_container_info(container_id: &str) -> Result<ContainerInfo> {
|
|
|
|
let mut container_info: ContainerInfo = toml::from_str(&info_str)?;
|
|
|
|
let mut container_info: ContainerInfo = toml::from_str(&info_str)?;
|
|
|
|
|
|
|
|
|
|
|
|
// todo 判断当前进程组 是否还有进程
|
|
|
|
// todo 判断当前进程组 是否还有进程
|
|
|
|
let cgroup = Cgroup::from(&container_info);
|
|
|
|
for pid in Cgroup::from(&container_info).procs {
|
|
|
|
|
|
|
|
container_info.procs.push(pid)
|
|
|
|
// 判断是否正在运行, 进入proc/pid/判断当前进程网络中是否有下面的设备
|
|
|
|
}
|
|
|
|
// let dev_path = Path::new("/proc").join(container_info.pid.to_string()).join("net").join("dev");
|
|
|
|
if container_info.procs.len() > 0 {
|
|
|
|
// let is_running = if let Ok(dev_text) = fs::read_to_string(dev_path){
|
|
|
|
|
|
|
|
// let slave_veth_name = format!("ro_{container_id}_3");
|
|
|
|
|
|
|
|
// dev_text.lines().any(|l|l.starts_with(&slave_veth_name))
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// false
|
|
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if cgroup.procs.len() > 0 {
|
|
|
|
|
|
|
|
container_info.status = ContainerStatus::RUNNING;
|
|
|
|
container_info.status = ContainerStatus::RUNNING;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
container_info.status = ContainerStatus::STOP;
|
|
|
|
container_info.status = ContainerStatus::STOP;
|
|
|
|
@ -607,7 +594,7 @@ fn get_all_container_info() -> Result<Vec<ContainerInfo>> {
|
|
|
|
|
|
|
|
|
|
|
|
/// 读取所有容器的状态
|
|
|
|
/// 读取所有容器的状态
|
|
|
|
fn show_containers(is_show_all: bool) -> Result<()> {
|
|
|
|
fn show_containers(is_show_all: bool) -> Result<()> {
|
|
|
|
println!("{:<10} {:<8} {:<10} {:<20} {:<20} {:<20} {:<10}", "id", "pid", "image", "run", "volume", "env", "status");
|
|
|
|
println!("{:<10} {:<10} {:<20} {:<20} {:<20} {:<10}", "id", "image", "run", "volume", "env", "status");
|
|
|
|
for container_info in get_all_container_info()? {
|
|
|
|
for container_info in get_all_container_info()? {
|
|
|
|
if is_show_all{
|
|
|
|
if is_show_all{
|
|
|
|
println!("{container_info}");
|
|
|
|
println!("{container_info}");
|
|
|
|
@ -686,7 +673,6 @@ fn stop_container(containers_id: &str, is_remove: bool) -> Result<()> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -704,7 +690,6 @@ fn main() -> Result<()>{
|
|
|
|
(Some(cmd), Some(image), None) => {
|
|
|
|
(Some(cmd), Some(image), None) => {
|
|
|
|
ContainerInfo {
|
|
|
|
ContainerInfo {
|
|
|
|
id: uuid::Uuid::new_v4().to_string()[0..8].to_string(),
|
|
|
|
id: uuid::Uuid::new_v4().to_string()[0..8].to_string(),
|
|
|
|
pid: -1,
|
|
|
|
|
|
|
|
run: cmd.clone(),
|
|
|
|
run: cmd.clone(),
|
|
|
|
image: image.clone(),
|
|
|
|
image: image.clone(),
|
|
|
|
volume: args.volume.clone().unwrap_or_default(),
|
|
|
|
volume: args.volume.clone().unwrap_or_default(),
|
|
|
|
@ -713,7 +698,8 @@ fn main() -> Result<()>{
|
|
|
|
log: args.log,
|
|
|
|
log: args.log,
|
|
|
|
wait: args.wait,
|
|
|
|
wait: args.wait,
|
|
|
|
cgroup_level: args.cgroup.clone().unwrap_or(CgroupLevel::default().to_string()),
|
|
|
|
cgroup_level: args.cgroup.clone().unwrap_or(CgroupLevel::default().to_string()),
|
|
|
|
root: args.root
|
|
|
|
root: args.root,
|
|
|
|
|
|
|
|
procs: vec![]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(None, None, Some(_container_id)) => {
|
|
|
|
(None, None, Some(_container_id)) => {
|
|
|
|
@ -761,6 +747,5 @@ fn main() -> Result<()>{
|
|
|
|
println!("容器{container_id}未运行");
|
|
|
|
println!("容器{container_id}未运行");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|