diff --git a/Makefile b/Makefile index 98d6a89..4d2b0c0 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ install: mkdir -p $(WORKSPACE)/images mkdir -p $(WORKSPACE)/volumes mkdir -p $(WORKSPACE)/containers + touch $(WORKSPACE)/network chmod -R 777 $(WORKSPACE) cp images/* $(WORKSPACE)/images/ chown -R rocker:rocker $(WORKSPACE) diff --git a/src/main.rs b/src/main.rs index 1fd9270..e18ccfd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ -use std::{io, fs, fmt, os, path, process, time}; +use std::{io, fs, fmt, os, path, process, time, sync, thread, env}; use fmt::Display; use os::fd::{AsFd, AsRawFd}; use os::unix::{fs::PermissionsExt, process::CommandExt}; use path::{Path, PathBuf}; -use std::sync::OnceLock; +use sync::OnceLock; use nix::sched::{clone, CloneCb, CloneFlags, setns}; use nix::sys::wait::{waitpid, WaitPidFlag}; @@ -116,6 +116,7 @@ fn extend_image(image_name: &String) -> Result { let volume_path_str = volume_path.to_str().unwrap(); // 安全的unwrap // 解压缩 + println!("解压镜像: {image_name:?}"); let out = process::Command::new("tar") .arg("-xvf") .arg(image_path_str) @@ -134,7 +135,7 @@ fn extend_image(image_name: &String) -> Result { Ok(volume_path) } else { // 删除 volume_path - std::fs::remove_dir_all(volume_path)?; + fs::remove_dir_all(volume_path)?; let std_err = String::from_utf8_lossy(&out.stderr); Err(RockerError::from(io::Error::new(io::ErrorKind::Other, format!("解压缩镜像失败: {std_err}")))) } @@ -218,8 +219,8 @@ fn init_container_custom_volume>(container_merged_path: P, custom } fn clear_env() { - for (k, _) in std::env::vars(){ - std::env::remove_var(k); + for (k, _) in env::vars(){ + env::remove_var(k); } } @@ -238,7 +239,7 @@ fn init_container_env(env_vec: &Vec) -> Result<()>{ for item_env in env_vec.iter() { let item_env_v = item_env.split("=").collect::>(); if item_env_v.len() == 2 { - std::env::set_var(item_env_v[0], item_env_v[1]) + env::set_var(item_env_v[0], item_env_v[1]) } else { if item_env.len() > 0 { println!("env 格式不正确: {item_env}") @@ -254,8 +255,8 @@ fn init_container_pivot>(merged_path: P) -> Result<()> { mount(None::<&str>, "/", None::<&str>, MsFlags::MS_PRIVATE | MsFlags::MS_REC, None::<&str>)?; // 修改overlayfs 为rootfs - std::env::set_current_dir(merged_path)?; - let pwd_path = std::env::current_dir()?; + env::set_current_dir(merged_path)?; + let pwd_path = env::current_dir()?; let pwd_str = pwd_path.to_string_lossy().to_string(); // 挂载bind todo @@ -269,11 +270,11 @@ fn init_container_pivot>(merged_path: P) -> Result<()> { pivot_root(pwd_str.as_str(), pivot_root_dir.as_str())?; // 修改当前进程工作目录(注意我们之前已经到rootfs内, 并且把根目录设置完毕了) - std::env::set_current_dir("/")?; + env::set_current_dir("/")?; // 卸载 old_root, 并删除临时文件 umount2(".pivot_root", MntFlags::MNT_DETACH).unwrap(); - std::fs::remove_dir(".pivot_root").unwrap(); + fs::remove_dir(".pivot_root").unwrap(); Ok(()) } @@ -372,14 +373,14 @@ fn start(container_info: &ContainerInfo, cb: CloneCb, clong_flags: CloneFlags, c // 删除 pause标志文件, 解开阻塞, 使其执行exec (0..100).any(|i| { - std::thread::sleep(std::time::Duration::from_millis(i)); - std::fs::remove_file(container_merged_pause_path).is_ok() + thread::sleep(time::Duration::from_millis(i)); + fs::remove_file(container_merged_pause_path).is_ok() }); // 检查是否执行exec了 - let main_exe = std::env::current_exe()?; + let main_exe = env::current_exe()?; for i in 0..100 { - std::thread::sleep(std::time::Duration::from_millis(i)); + thread::sleep(time::Duration::from_millis(i)); if let Ok(true) = check_container_is_running(&child_pid, &main_exe) { break; } @@ -447,7 +448,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) - init_container_env(&env_vec).unwrap(); create_pause(container_root_pause_path).unwrap(); while container_merged_pause_path.exists() { - std::thread::sleep(std::time::Duration::from_millis(10)); + thread::sleep(time::Duration::from_millis(10)); } let cmd_vec = exec_cmd.split(" ").collect::>(); @@ -499,7 +500,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) - // 暂停等待外部主进程设置网络设备 create_pause(&container_root_pause_path).unwrap(); while container_root_pause_path.exists() { - std::thread::sleep(std::time::Duration::from_millis(10)); + thread::sleep(time::Duration::from_millis(10)); } let cmd_vec = container_info.run.split(" ").collect::>(); @@ -524,7 +525,7 @@ enum ContainerStatus { } impl Display for ContainerStatus { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::READY => write!(f, "😀"), Self::RUNNING => write!(f, "{Y}"), @@ -561,7 +562,7 @@ impl ContainerInfo { } impl Display for ContainerInfo { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let volume: String = self.volume.chars().take(20).collect(); let env: String = self.env.chars().take(20).collect(); let run: String = self.run.chars().take(20).collect(); diff --git a/src/network.rs b/src/network.rs index aafa77e..7601853 100644 --- a/src/network.rs +++ b/src/network.rs @@ -1,4 +1,7 @@ -use std::{fmt::{Display, Formatter}, fs::OpenOptions, io::{stdout, Read, Write}}; +use std::{io, fs, fmt, path}; +use fmt::{Display, Formatter}; +use io::{Read, Write}; +use path::Path; use rand::Rng; static NETWORK_FILE: &str = "/home/rocker/network"; @@ -6,8 +9,8 @@ static NETWORK_FILE: &str = "/home/rocker/network"; #[derive(Debug, Clone)] struct NetWrok { - gateway_addr: String, // 192.168.124.0 - bridge_addr: String, // 192.168.124.1 + gateway_addr: String, // 192.168.124.0 + bridge_addr: String, // 192.168.124.1 slave_addr: String, bridge_name: String, // ro_uuid[:8]_1 // ip 就是 192.168.124.1 @@ -54,17 +57,27 @@ fn set_snat(gateway_addr: &str, bridge_name: &str, action: &str) -> bool { true } -fn get_all_network() -> Vec { +fn take_all_network() -> Vec { // 打开 NETWORK_FILE 所有已经配置的信息, 如果没有则创建 - let mut f = OpenOptions::new() + let network_file_paht = Path::new(NETWORK_FILE); + if (0..100).any(|i| { + std::thread::sleep(std::time::Duration::from_millis(i)); + network_file_paht.exists() + }) == false { + println!("🔴 网络设备逻辑锁获取失败"); + }; + + let mut f = fs::OpenOptions::new() .write(true) - .create(true) .read(true) .open(NETWORK_FILE) .unwrap(); let mut text = String::new(); f.read_to_string(&mut text).unwrap(); + // 逻辑锁, 删除 NETWORK_FILE文件, 由外部修改后更新算了, 暂时这么设计 + let _ = fs::remove_file(NETWORK_FILE); + let mut all_network = vec![]; for line in text.lines() { let network_info_vec = line.split(",").collect::>(); @@ -76,14 +89,14 @@ fn get_all_network() -> Vec { master_veth_name: network_info_vec[4].to_string(), slave_veth_name: network_info_vec[5].to_string(), }) - } + all_network } fn write_network_info(all_network: Vec) { - let mut f = OpenOptions::new() + let mut f = fs::OpenOptions::new() .write(true) .create(true) .truncate(true) @@ -127,7 +140,7 @@ fn del_dev(dev_name: &str) -> bool { pub fn remove_network(uuid_name: &str) { - let mut all_network = get_all_network(); + let mut all_network = take_all_network(); let mut network = None; all_network = all_network.into_iter() .filter_map(|n| { @@ -144,7 +157,7 @@ pub fn remove_network(uuid_name: &str) { del_dev(&network.master_veth_name); set_snat(&network.gateway_addr, &network.bridge_name, "-D"); } - // 回写到文件中 + // 回写到文件中 write_network_info(all_network); println!("删除网络设备: {uuid_name}"); } @@ -153,7 +166,7 @@ pub fn remove_network(uuid_name: &str) { pub fn create_network(uuid_name: &str, pid: i32) -> bool { let pid = pid.to_string(); // 创建一个随机地址段的 没分配过的ip - let mut all_network = get_all_network(); + let mut all_network = take_all_network(); let mut rg = rand::thread_rng(); let network = loop {