Feat cni (#7)

* fmt

* 完善cni以及添加接口
This commit is contained in:
火花
2025-03-23 11:13:42 +08:00
committed by GitHub
parent c33fefa635
commit 9fa472c8c6
8 changed files with 279 additions and 14 deletions

View File

@ -23,16 +23,28 @@ use oci_spec::image::{Arch, ImageConfiguration, ImageIndex, ImageManifest, Media
use prost_types::Any;
use sha2::{Digest, Sha256};
use spec::{DEFAULT_NAMESPACE, generate_spec};
use std::{fs, sync::Arc, time::Duration, vec};
use std::{
collections::HashMap,
fs,
sync::{Arc, RwLock},
time::Duration,
vec,
};
use tokio::time::timeout;
// config.json,dockerhub密钥
// const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/";
type NetnsMap = Arc<RwLock<HashMap<String, (String, String)>>>;
lazy_static::lazy_static! {
static ref GLOBAL_NETNS_MAP: NetnsMap = Arc::new(RwLock::new(HashMap::new()));
}
type Err = Box<dyn std::error::Error>;
pub struct Service {
client: Arc<Client>,
netns_map: NetnsMap,
}
impl Service {
@ -40,9 +52,25 @@ impl Service {
let client = Client::from_path(endpoint).await.unwrap();
Ok(Service {
client: Arc::new(client),
netns_map: GLOBAL_NETNS_MAP.clone(),
})
}
pub async fn save_netns_ip(&self, cid: &str, netns: &str, ip: &str) {
let mut map = self.netns_map.write().unwrap();
map.insert(cid.to_string(), (netns.to_string(), ip.to_string()));
}
pub async fn get_netns_ip(&self, cid: &str) -> Option<(String, String)> {
let map = self.netns_map.read().unwrap();
map.get(cid).cloned()
}
pub async fn remove_netns_ip(&self, cid: &str) {
let mut map = self.netns_map.write().unwrap();
map.remove(cid);
}
async fn prepare_snapshot(&self, cid: &str, ns: &str) -> Result<Vec<Mount>, Err> {
let parent_snapshot = self.get_parent_snapshot(cid, ns).await?;
let req = PrepareSnapshotRequest {
@ -69,8 +97,8 @@ impl Service {
};
let _mount = self.prepare_snapshot(cid, ns).await?;
let spec_path = generate_spec(&cid, ns).unwrap();
let (env, args) = self.get_env_and_args(image_name, ns).await?;
let spec_path = generate_spec(&cid, ns, args, env).unwrap();
let spec = fs::read_to_string(spec_path).unwrap();
let spec = Any {
@ -96,10 +124,10 @@ impl Service {
container: Some(container),
};
let req = with_namespace!(req, namespace);
// let req = with_namespace!(req, namespace);
let _resp = containers_client
.create(req)
.create(with_namespace!(req, namespace))
.await
.expect("Failed to create container");
@ -162,6 +190,7 @@ impl Service {
.delete(with_namespace!(delete_request, namespace))
.await
.expect("Failed to delete container");
self.remove_netns_ip(cid).await;
// println!("Container: {:?} deleted", cc);
} else {
@ -191,7 +220,8 @@ impl Service {
Ok(())
}
async fn create_task(&self, cid: &str, ns: &str) -> Result<(), Err> {
/// 返回任务的pid
async fn create_task(&self, cid: &str, ns: &str) -> Result<u32, Err> {
let mut sc = self.client.snapshots();
let req = MountsRequest {
snapshotter: "overlayfs".to_string(),
@ -203,15 +233,17 @@ impl Service {
.into_inner()
.mounts;
drop(sc);
let (ip, path) = cni::cni_network::create_cni_network(cid.to_string(), ns.to_string())?;
self.save_netns_ip(cid, &path, &ip).await;
let mut tc = self.client.tasks();
let req = CreateTaskRequest {
container_id: cid.to_string(),
rootfs: mounts,
..Default::default()
};
let _resp = tc.create(with_namespace!(req, ns)).await?;
Ok(())
let resp = tc.create(with_namespace!(req, ns)).await?;
let pid = resp.into_inner().pid;
Ok(pid)
}
async fn start_task(&self, cid: &str, ns: &str) -> Result<(), Err> {
@ -578,6 +610,21 @@ impl Service {
Ok(ret)
}
async fn get_env_and_args(
&self,
name: &str,
ns: &str,
) -> Result<(Vec<String>, Vec<String>), Err> {
let img_config = self.get_img_config(name, ns).await.unwrap();
if let Some(config) = img_config.config() {
let env = config.env().as_ref().map_or_else(Vec::new, |v| v.clone());
let args = config.cmd().as_ref().map_or_else(Vec::new, |v| v.clone());
Ok((env, args))
} else {
Err("No config found".into())
}
}
fn check_namespace(&self, ns: &str) -> String {
match ns {
"" => DEFAULT_NAMESPACE.to_string(),

View File

@ -103,6 +103,7 @@ pub struct LinuxDeviceCgroup {
pub struct LinuxNamespace {
#[serde(rename = "type")]
pub type_: String,
pub path: Option<String>,
}
pub fn default_unix_caps() -> Vec<String> {
@ -150,22 +151,27 @@ fn default_readonly_paths() -> Vec<String> {
]
}
fn default_unix_namespaces() -> Vec<LinuxNamespace> {
fn default_unix_namespaces(ns: &str, cid: &str) -> Vec<LinuxNamespace> {
vec![
LinuxNamespace {
type_: String::from(PID_NAMESPACE),
path: None,
},
LinuxNamespace {
type_: String::from(IPC_NAMESPACE),
path: None,
},
LinuxNamespace {
type_: String::from(UTS_NAMESPACE),
path: None,
},
LinuxNamespace {
type_: String::from(MOUNT_NAMESPACE),
path: None,
},
LinuxNamespace {
type_: String::from(NETWORK_NAMESPACE),
path: Some(format!("/var/run/netns/{}", get_netns(ns, cid))),
},
]
}
@ -294,7 +300,7 @@ pub fn populate_default_unix_spec(id: &str, ns: &str) -> Spec {
access: RWM.to_string(),
}],
},
namespaces: default_unix_namespaces(),
namespaces: default_unix_namespaces(ns, id),
},
mounts: default_mounts(),
}
@ -306,12 +312,23 @@ pub fn save_spec_to_file(spec: &Spec, path: &str) -> Result<(), std::io::Error>
Ok(())
}
pub fn generate_spec(id: &str, ns: &str) -> Result<String, std::io::Error> {
fn get_netns(ns: &str, cid: &str) -> String {
format!("{}-{}", ns, cid)
}
pub fn generate_spec(
id: &str,
ns: &str,
args: Vec<String>,
env: Vec<String>,
) -> Result<String, std::io::Error> {
let namespace = match ns {
"" => DEFAULT_NAMESPACE,
_ => ns,
};
let spec = populate_default_unix_spec(id, ns);
let mut spec = populate_default_unix_spec(id, ns);
spec.process.args = args;
spec.process.env = env;
let path = format!("{}/{}/{}.json", PATH_TO_SPEC_PREFIX, namespace, id);
save_spec_to_file(&spec, &path)?;
Ok(path)