From ab94f96457f4cd2b11f8c3619de1bf8b3e7e2524 Mon Sep 17 00:00:00 2001 From: sparkzky Date: Wed, 26 Feb 2025 13:19:00 +0800 Subject: [PATCH 1/6] init --- container_spec.json | 430 +++++++++++++++----------------------------- service/src/lib.rs | 15 +- service/src/spec.rs | 297 ++++++++++++++++++++++++++++++ 3 files changed, 454 insertions(+), 288 deletions(-) create mode 100644 service/src/spec.rs diff --git a/container_spec.json b/container_spec.json index b17221b..ea26e4f 100644 --- a/container_spec.json +++ b/container_spec.json @@ -1,290 +1,158 @@ - { - "ID": "hello", - "Labels": { - "io.containerd.image.config.stop-signal": "SIGTERM" + "ociVersion": "1.0.0-rc2-dev", + "platform": { + "os": "linux", + "arch": "amd64" }, - "Image": "docker.io/library/hello-world:latest", - "Runtime": { - "Name": "io.containerd.runc.v2", - "Options": { - "type_url": "containerd.runc.v1.Options" - }susu - }, - "SnapshotKey": "hello", - "Snapshotter": "overlayfs", - "CreatedAt": "2025-01-25T10:08:43.259272017Z", - "UpdatedAt": "2025-01-25T10:08:43.259272017Z", - "Extensions": {}, - "SandboxID": "", - "Spec": { - "ociVersion": "1.1.0", - "process": { - "user": { - "uid": 0, - "gid": 0, - "additionalGids": [ - 0 - ] - }, - "args": [ - "/hello" - ], - "env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - ], - "cwd": "/", - "capabilities": { - "bounding": [ - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_FSETID", - "CAP_FOWNER", - "CAP_MKNOD", - "CAP_NET_RAW", - "CAP_SETGID", - "CAP_SETUID", - "CAP_SETFCAP", - "CAP_SETPCAP", - "CAP_NET_BIND_SERVICE", - "CAP_SYS_CHROOT", - "CAP_KILL", - "CAP_AUDIT_WRITE" - ], - "effective": [ - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_FSETID", - "CAP_FOWNER", - "CAP_MKNOD", - "CAP_NET_RAW", - "CAP_SETGID", - "CAP_SETUID", - "CAP_SETFCAP", - "CAP_SETPCAP", - "CAP_NET_BIND_SERVICE", - "CAP_SYS_CHROOT", - "CAP_KILL", - "CAP_AUDIT_WRITE" - ], - "permitted": [ - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_FSETID", - "CAP_FOWNER", - "CAP_MKNOD", - "CAP_NET_RAW", - "CAP_SETGID", - "CAP_SETUID", - "CAP_SETFCAP", - "CAP_SETPCAP", - "CAP_NET_BIND_SERVICE", - "CAP_SYS_CHROOT", - "CAP_KILL", - "CAP_AUDIT_WRITE" - ] - }, - "rlimits": [ - { - "type": "RLIMIT_NOFILE", - "hard": 1024, - "soft": 1024 - } - ], - "noNewPrivileges": true + "process": { + "terminal": false, + "consoleSize": { + "height": 0, + "width": 0 }, - "root": { - "path": "rootfs" + "user": { + "uid": 0, + "gid": 0 }, - "mounts": [ - { - "destination": "/proc", - "type": "proc", - "source": "proc", - "options": [ - "nosuid", - "noexec", - "nodev" - ] - }, - { - "destination": "/dev", - "type": "tmpfs", - "source": "tmpfs", - "options": [ - "nosuid", - "strictatime", - "mode=755", - "size=65536k" - ] - }, - { - "destination": "/dev/pts", - "type": "devpts", - "source": "devpts", - "options": [ - "nosuid", - "noexec", - "newinstance", - "ptmxmode=0666", - "mode=0620", - "gid=5" - ] - }, - { - "destination": "/dev/shm", - "type": "tmpfs", - "source": "shm", - "options": [ - "nosuid", - "noexec", - "nodev", - "mode=1777", - "size=65536k" - ] - }, - { - "destination": "/dev/mqueue", - "type": "mqueue", - "source": "mqueue", - "options": [ - "nosuid", - "noexec", - "nodev" - ] - }, - { - "destination": "/sys", - "type": "sysfs", - "source": "sysfs", - "options": [ - "nosuid", - "noexec", - "nodev", - "ro" - ] - }, - { - "destination": "/run", - "type": "tmpfs", - "source": "tmpfs", - "options": [ - "nosuid", - "strictatime", - "mode=755", - "size=65536k" - ] - } + "args": [ "echo", "$OUTPUT" ], + "env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "TERM=xterm" ], - "linux": { - "resources": { - "devices": [ - { - "allow": false, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 3, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 8, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 7, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 5, - "minor": 0, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 5, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 9, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 5, - "minor": 1, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 136, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 5, - "minor": 2, - "access": "rwm" - } - ] - }, - "cgroupsPath": "/default/hello", - "namespaces": [ - { - "type": "pid" - }, - { - "type": "ipc" - }, - { - "type": "uts" - }, - { - "type": "mount" - }, - { - "type": "network" - } - ], - "maskedPaths": [ - "/proc/acpi", - "/proc/asound", - "/proc/kcore", - "/proc/keys", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/sys/firmware", - "/sys/devices/virtual/powercap", - "/proc/scsi" - ], - "readonlyPaths": [ - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger" + "cwd": "/", + "rlimits": [{ + "type": "RLIMIT_NOFILE", + "hard": 1024, + "soft": 1024 + }], + "noNewPrivileges": true + }, + "root": { + "path": "$ROOTFS", + "readonly": false + }, + "hostname": "test", + "mounts": [{ + "destination": "/proc", + "type": "proc", + "source": "proc" + }, + { + "destination": "/dev", + "type": "tmpfs", + "source": "tmpfs", + "options": [ + "nosuid", + "strictatime", + "mode=755", + "size=65536k" + ] + }, + { + "destination": "/dev/pts", + "type": "devpts", + "source": "devpts", + "options": [ + "nosuid", + "noexec", + "newinstance", + "ptmxmode=0666", + "mode=0620", + "gid=5" + ] + }, + { + "destination": "/dev/shm", + "type": "tmpfs", + "source": "shm", + "options": [ + "nosuid", + "noexec", + "nodev", + "mode=1777", + "size=65536k" + ] + }, + { + "destination": "/dev/mqueue", + "type": "mqueue", + "source": "mqueue", + "options": [ + "nosuid", + "noexec", + "nodev" + ] + }, + { + "destination": "/sys", + "type": "sysfs", + "source": "sysfs", + "options": [ + "nosuid", + "noexec", + "nodev", + "ro" + ] + }, + { + "destination": "/sys/fs/cgroup", + "type": "cgroup", + "source": "cgroup", + "options": [ + "nosuid", + "noexec", + "nodev", + "relatime", + "ro" ] } + ], + "hooks": {}, + "linux": { + "devices": [], + "cgroupsPath": "kata/vfiotest", + "resources": { + "devices": [ + {"allow":false,"access":"rwm"}, + {"allow":true,"type":"c","major":1,"minor":3,"access":"rwm"}, + {"allow":true,"type":"c","major":1,"minor":5,"access":"rwm"}, + {"allow":true,"type":"c","major":1,"minor":8,"access":"rwm"}, + {"allow":true,"type":"c","major":1,"minor":9,"access":"rwm"}, + {"allow":true,"type":"c","major":5,"minor":0,"access":"rwm"}, + {"allow":true,"type":"c","major":5,"minor":1,"access":"rwm"} + ] + }, + "namespaces": [{ + "type": "pid" + }, + { + "type": "network" + }, + { + "type": "ipc" + }, + { + "type": "uts" + }, + { + "type": "mount" + } + ], + "maskedPaths": [ + "/proc/kcore", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware" + ], + "readonlyPaths": [ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] } } \ No newline at end of file diff --git a/service/src/lib.rs b/service/src/lib.rs index 38688d4..f63c7a5 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -1,3 +1,5 @@ +pub mod spec; + use containerd_client::{ services::v1::{ container::Runtime, Container, CreateContainerRequest, CreateTaskRequest, @@ -36,11 +38,11 @@ impl Service { } pub async fn create_container(&self, image: String, cid: String) { - // let spec = include_str!("../../container_spec.json").to_string(); - // let spec = Any { - // type_url: "types.containerd.io/opencontainers/runtime-spec/1/Spec".to_string(), - // value: spec.into_bytes(), - // }; + let spec = include_str!("../../container_spec.json").to_string(); + let spec = Any { + type_url: "types.containerd.io/opencontainers/runtime-spec/1/Spec".to_string(), + value: spec.into_bytes(), + }; let mut containers_client = self.client.lock().unwrap().containers(); let container = Container { id: cid.to_string(), @@ -49,7 +51,7 @@ impl Service { name: "io.containerd.runc.v2".to_string(), options: None, }), - // spec: Some(spec), + spec: Some(spec), ..Default::default() }; @@ -259,7 +261,6 @@ impl Service { pub fn get_resolver(&self) { todo!() } - } //容器是容器,要先启动,然后才能运行任务 //要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。 diff --git a/service/src/spec.rs b/service/src/spec.rs new file mode 100644 index 0000000..0cc482b --- /dev/null +++ b/service/src/spec.rs @@ -0,0 +1,297 @@ +use serde::{Deserialize, Serialize}; +use std::fs::File; + +// 定义版本的常量 +const VERSION_MAJOR: u32 = 1; +const VERSION_MINOR: u32 = 1; +const VERSION_PATCH: u32 = 0; +const VERSION_DEV: &str = ""; // 对应开发分支 + +const RWM: &str = "rwm"; +const DEFAULT_ROOTFS_PATH: &str = "rootfs"; + +const DEFAULT_UNIX_ENV:&str="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; + +const PID_NAMESPACE: &str = "pid"; +const NETWORK_NAMESPACE: &str = "network"; +const MOUNT_NAMESPACE: &str = "mount"; +const IPC_NAMESPACE: &str = "ipc"; +const UTS_NAMESPACE: &str = "uts"; +const USER_NAMESPACE: &str = "user"; +const CGROUP_NAMESPACE: &str = "cgroup"; +const TIME_NAMESPACE: &str = "time"; + + +#[derive(Serialize, Deserialize, Debug)] +struct Spec { + ociVersion: String, + root: Root, + process: Process, + linux: Linux, + mounts: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct Root { + path: String, +} + +#[derive(Serialize, Deserialize, Debug)] +struct Process { + cwd: String, + noNewPrivileges: bool, + user: User, + capabilities: LinuxCapabilities, + rlimits: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct User { + uid: u32, + gid: u32, +} + +#[derive(Serialize, Deserialize, Debug)] +struct Mount { + destination: String, + type_: String, + source: String, + options: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct LinuxCapabilities { + bounding: Vec, + permitted: Vec, + effective: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct POSIXRlimit { + #[serde(rename = "type")] + type_: String, + hard: u64, + soft: u64, +} + +#[derive(Serialize, Deserialize, Debug)] +struct Linux { + masked_paths: Vec, + readonly_paths: Vec, + cgroups_path: String, + resources: LinuxResources, + namespaces: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct LinuxResources { + devices: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +struct LinuxDeviceCgroup { + allow: bool, + access: String, +} + +#[derive(Serialize, Deserialize, Debug)] +struct LinuxNamespace { + #[serde(rename = "type")] + type_: String, +} + +pub fn default_unix_caps() -> Vec { + vec![ + String::from("CAP_CHOWN"), + String::from("CAP_DAC_OVERRIDE"), + String::from("CAP_FSETID"), + String::from("CAP_FOWNER"), + String::from("CAP_MKNOD"), + String::from("CAP_NET_RAW"), + String::from("CAP_SETGID"), + String::from("CAP_SETUID"), + String::from("CAP_SETFCAP"), + String::from("CAP_SETPCAP"), + String::from("CAP_NET_BIND_SERVICE"), + String::from("CAP_SYS_CHROOT"), + String::from("CAP_KILL"), + String::from("CAP_AUDIT_WRITE"), + ] +} + +fn default_masked_parhs() -> Vec { + vec![ + String::from("/proc/acpi"), + String::from("/proc/asound"), + String::from("/proc/kcore"), + String::from("/proc/keys"), + String::from("/proc/latency_stats"), + String::from("/proc/timer_list"), + String::from("/proc/timer_stats"), + String::from("/proc/sched_debug"), + String::from("/proc/scsi"), + String::from("/sys/firmware"), + String::from("/sys/devices/virtual/powercap"), + ] +} + +fn default_readonly_paths() -> Vec { + vec![ + String::from("/proc/bus"), + String::from("/proc/fs"), + String::from("/proc/irq"), + String::from("/proc/sys"), + String::from("/proc/sysrq-trigger"), + ] +} + +fn default_unix_namespaces() -> Vec { + vec![ + LinuxNamespace { + type_: String::from(PID_NAMESPACE), + }, + LinuxNamespace { + type_: String::from(IPC_NAMESPACE), + }, + LinuxNamespace { + type_: String::from(UTS_NAMESPACE), + }, + LinuxNamespace { + type_: String::from(MOUNT_NAMESPACE), + }, + LinuxNamespace { + type_: String::from(NETWORK_NAMESPACE), + }, + ] +} + +fn default_mounts() -> Vec { + vec![ + Mount { + destination: "/proc".to_string(), + type_: "proc".to_string(), + source: "proc".to_string(), + options: vec![], + }, + Mount { + destination: "/dev".to_string(), + type_: "tmpfs".to_string(), + source: "tmpfs".to_string(), + options: vec![ + "nosuid".to_string(), + "strictatime".to_string(), + "mode=755".to_string(), + "size=65536k".to_string(), + ], + }, + Mount { + destination: "/dev/pts".to_string(), + type_: "devpts".to_string(), + source: "devpts".to_string(), + options: vec![ + "nosuid".to_string(), + "noexec".to_string(), + "newinstance".to_string(), + "ptmxmode=0666".to_string(), + "mode=0620".to_string(), + "gid=5".to_string(), + ], + }, + Mount { + destination: "/dev/shm".to_string(), + type_: "tmpfs".to_string(), + source: "shm".to_string(), + options: vec![ + "nosuid".to_string(), + "noexec".to_string(), + "nodev".to_string(), + "mode=1777".to_string(), + "size=65536k".to_string(), + ], + }, + Mount { + destination: "/dev/mqueue".to_string(), + type_: "mqueue".to_string(), + source: "mqueue".to_string(), + options: vec![ + "nosuid".to_string(), + "noexec".to_string(), + "nodev".to_string(), + ], + }, + Mount { + destination: "/sys".to_string(), + type_: "sysfs".to_string(), + source: "sysfs".to_string(), + options: vec![ + "nosuid".to_string(), + "noexec".to_string(), + "nodev".to_string(), + "ro".to_string(), + ], + }, + Mount { + destination: "/sys/fs/cgroup".to_string(), + type_: "cgroup".to_string(), + source: "cgroup".to_string(), + options: vec![ + "nosuid".to_string(), + "noexec".to_string(), + "nodev".to_string(), + "relatime".to_string(), + "ro".to_string(), + ], + }, + ] +} + +fn get_version() -> String { + format!( + "{}.{}.{}{}", + VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_DEV + ) +} + +fn populate_default_unix_spec(id: &str, ns: &str) -> Spec { + Spec { + ociVersion: get_version(), + root: Root { + path: DEFAULT_ROOTFS_PATH.to_string(), + }, + process: Process { + cwd: String::from("/"), + noNewPrivileges: true, + user: User { uid: 0, gid: 0 }, + capabilities: LinuxCapabilities { + bounding: default_unix_caps(), + permitted: default_unix_caps(), + effective: default_unix_caps(), + }, + rlimits: vec![POSIXRlimit { + type_: String::from("RLIMIT_NOFILE"), + hard: 1024, + soft: 1024, + }], + }, + linux: Linux { + masked_paths: default_masked_parhs(), + readonly_paths: default_readonly_paths(), + cgroups_path: format!("{}/{}", ns, id), + resources: LinuxResources { + devices: vec![LinuxDeviceCgroup { + allow: false, + access: String::from("rwm"), + }], + }, + namespaces: default_unix_namespaces(), + }, + mounts: default_mounts(), + } +} + +fn save_spec_to_file(spec: &Spec, path: &str) -> Result<(), std::io::Error> { + let file = File::create(path)?; + serde_json::to_writer(file, spec)?; + Ok(()) +} + From fa084b1f23361d0ebd2bb88b79967040fcd31522 Mon Sep 17 00:00:00 2001 From: sparkzky Date: Thu, 27 Feb 2025 21:30:07 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AF=B9ctr=E7=9A=84?= =?UTF-8?q?=E5=8C=85=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/handlers.rs | 15 +- app/src/types.rs | 3 + service/Cargo.toml | 5 +- service/src/lib.rs | 445 +++++++++++++++++++++++++++++++++++--------- service/src/spec.rs | 153 ++++++++------- 5 files changed, 458 insertions(+), 163 deletions(-) diff --git a/app/src/handlers.rs b/app/src/handlers.rs index 3b5ca5c..4e6d55c 100644 --- a/app/src/handlers.rs +++ b/app/src/handlers.rs @@ -10,7 +10,8 @@ pub async fn create_container( ) -> impl Responder { let cid = info.container_id.clone(); let image = info.image.clone(); - service.create_container(image, cid).await; + let ns = info.ns.clone(); + service.create_container(&image, &cid, &ns).await.unwrap(); HttpResponse::Ok().json("Container created successfully!") } @@ -20,12 +21,18 @@ pub async fn remove_container( info: web::Json, ) -> impl Responder { let container_id = info.container_id.clone(); - service.remove_container(container_id).await; + let ns = info.ns.clone(); + service.remove_container(&container_id, &ns).await.unwrap(); HttpResponse::Ok().json("Container removed successfully!") } -pub async fn get_container_list(service: web::Data>) -> impl Responder { - let container_list = service.get_container_list().await.unwrap(); +/// 获取容器列表 +pub async fn get_container_list( + service: web::Data>, + info: web::Json, +) -> impl Responder { + let ns = info.ns.clone(); + let container_list = service.get_container_list(&ns).await.unwrap(); HttpResponse::Ok().json(container_list) } diff --git a/app/src/types.rs b/app/src/types.rs index d3b52df..9b843e6 100644 --- a/app/src/types.rs +++ b/app/src/types.rs @@ -4,14 +4,17 @@ use serde::{Deserialize, Serialize}; pub struct CreateContainerInfo { pub container_id: String, pub image: String, + pub ns: String, } #[derive(Serialize, Deserialize)] pub struct RemoveContainerInfo { pub container_id: String, + pub ns: String, } #[derive(Deserialize)] pub struct GetContainerListQuery { pub status: Option, + pub ns: String, } diff --git a/service/Cargo.toml b/service/Cargo.toml index 481b9a4..09a441c 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -11,4 +11,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" log = "0.4" env_logger = "0.10" -prost-types = "0.13.4" \ No newline at end of file +prost-types = "0.13.4" +oci-spec = "0.6" +sha2 = "0.10" +hex = "0.4" \ No newline at end of file diff --git a/service/src/lib.rs b/service/src/lib.rs index f63c7a5..212fe0b 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -1,25 +1,30 @@ -pub mod spec; +pub mod spec; use containerd_client::{ services::v1::{ - container::Runtime, Container, CreateContainerRequest, CreateTaskRequest, - DeleteContainerRequest, DeleteTaskRequest, GetImageRequest, KillRequest, - ListContainersRequest, ListTasksRequest, StartRequest, WaitRequest, + container::Runtime, + snapshots::{MountsRequest, PrepareSnapshotRequest}, + Container, CreateContainerRequest, CreateTaskRequest, DeleteContainerRequest, + DeleteTaskRequest, GetImageRequest, KillRequest, ListContainersRequest, ListTasksRequest, + ReadContentRequest, StartRequest, WaitRequest, }, tonic::Request, + types::Mount, with_namespace, Client, }; +use oci_spec::image::{Arch, ImageConfiguration, ImageIndex, ImageManifest, MediaType, Os}; use prost_types::Any; +use sha2::{Digest, Sha256}; +use spec::generate_spec; use std::{ - collections::HashMap, - fs::{self, File}, + fs, sync::{Arc, Mutex}, time::Duration, }; use tokio::time::timeout; // config.json,dockerhub密钥 -const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/"; +// const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/"; // 命名空间(容器的) const NAMESPACE: &str = "default"; @@ -37,21 +42,59 @@ impl Service { }) } - pub async fn create_container(&self, image: String, cid: String) { - let spec = include_str!("../../container_spec.json").to_string(); + async fn prepare_snapshot(&self, cid: &str, ns: &str) -> Result, Err> { + let parent_snapshot = self.get_parent_snapshot(cid, ns).await?; + let req = PrepareSnapshotRequest { + snapshotter: "overlayfs".to_string(), + key: cid.to_string(), + parent: parent_snapshot, + ..Default::default() + }; + let resp = self + .client + .lock() + .unwrap() + .snapshots() + .prepare(with_namespace!(req, ns)) + .await? + .into_inner() + .mounts; + + Ok(resp) + } + + pub async fn create_container( + &self, + image_name: &str, + cid: &str, + ns: &str, + ) -> Result<(), Err> { + let namespace = match ns { + "" => spec::DEFAULT_NAMESPACE, + _ => ns, + }; + + let _mount = self.prepare_snapshot(cid, ns).await?; + + let spec_path = generate_spec(&cid, ns).unwrap(); + let spec = fs::read_to_string(spec_path).unwrap(); + let spec = Any { type_url: "types.containerd.io/opencontainers/runtime-spec/1/Spec".to_string(), value: spec.into_bytes(), }; + let mut containers_client = self.client.lock().unwrap().containers(); let container = Container { id: cid.to_string(), - image, + image: image_name.to_string(), runtime: Some(Runtime { name: "io.containerd.runc.v2".to_string(), options: None, }), spec: Some(spec), + snapshotter: "overlayfs".to_string(), + snapshot_key: cid.to_string(), ..Default::default() }; @@ -59,38 +102,49 @@ impl Service { container: Some(container), }; - let req = with_namespace!(req, NAMESPACE); + let req = with_namespace!(req, namespace); let _resp = containers_client .create(req) .await .expect("Failed to create container"); - println!("Container: {:?} created", cid); + // println!("Container: {:?} created", cid); + Ok(()) } - pub async fn remove_container(&self, container_id: String) { + pub async fn remove_container(&self, cid: &str, ns: &str) -> Result<(), Err> { + let namespace = match ns { + "" => NAMESPACE, + _ => ns, + }; let c = self.client.lock().unwrap(); - let mut containers_client = c.containers(); - let request = Request::new(ListContainersRequest { + let request = ListContainersRequest { ..Default::default() - }); + }; + let mut cc = c.containers(); - let responce = containers_client.list(request).await.unwrap().into_inner(); + let responce = cc + .list(with_namespace!(request, namespace)) + .await? + .into_inner(); let container = responce .containers .iter() - .find(|container| container.id == container_id); + .find(|container| container.id == cid); if let Some(container) = container { - let mut tasks_client = c.tasks(); + let mut tc = c.tasks(); - let request = Request::new(ListTasksRequest { - filter: format!("container=={}", container_id), + let request = ListTasksRequest { + filter: format!("container=={}", cid), ..Default::default() - }); - let responce = tasks_client.list(request).await.unwrap().into_inner(); - drop(tasks_client); + }; + let responce = tc + .list(with_namespace!(request, namespace)) + .await? + .into_inner(); + drop(tc); if let Some(task) = responce .tasks .iter() @@ -104,79 +158,104 @@ impl Service { // TASK_EXITED (4) — 任务已退出 // TASK_PAUSED (5) — 任务已暂停 // TASK_FAILED (6) — 任务失败 - self.delete_task(&task.container_id).await; + self.delete_task(&task.container_id, ns).await; } let delete_request = DeleteContainerRequest { id: container.id.clone(), ..Default::default() }; - let delete_request = with_namespace!(delete_request, NAMESPACE); - let _ = containers_client - .delete(delete_request) + let _ = cc + .delete(with_namespace!(delete_request, namespace)) .await .expect("Failed to delete container"); - println!("Container: {:?} deleted", containers_client); + // println!("Container: {:?} deleted", cc); } else { todo!("Container not found"); } - drop(containers_client); + drop(cc); + Ok(()) } - pub async fn create_and_start_task(&self, container_id: String) { - let tmp = std::env::temp_dir().join("containerd-client-test"); - println!("Temp dir: {:?}", tmp); - fs::create_dir_all(&tmp).expect("Failed to create temp directory"); - let stdin = tmp.join("stdin"); - let stdout = tmp.join("stdout"); - let stderr = tmp.join("stderr"); - File::create(&stdin).expect("Failed to create stdin"); - File::create(&stdout).expect("Failed to create stdout"); - File::create(&stderr).expect("Failed to create stderr"); + pub async fn create_and_start_task(&self, cid: &str, ns: &str) -> Result<(), Err> { + // let tmp = std::env::temp_dir().join("containerd-client-test"); + // println!("Temp dir: {:?}", tmp); + // fs::create_dir_all(&tmp).expect("Failed to create temp directory"); + // let stdin = tmp.join("stdin"); + // let stdout = tmp.join("stdout"); + // let stderr = tmp.join("stderr"); + // File::create(&stdin).expect("Failed to create stdin"); + // File::create(&stdout).expect("Failed to create stdout"); + // File::create(&stderr).expect("Failed to create stderr"); - let mut tasks_client = self.client.lock().unwrap().tasks(); + let namespace = match ns { + "" => spec::DEFAULT_NAMESPACE, + _ => ns, + }; + self.create_task(cid, namespace).await?; + self.start_task(cid, namespace).await?; + Ok(()) + } + async fn create_task(&self, cid: &str, ns: &str) -> Result<(), Err> { + let c = self.client.lock().unwrap(); + let mut sc = c.snapshots(); + let req = MountsRequest { + snapshotter: "overlayfs".to_string(), + key: cid.to_string(), + }; + let mounts = sc + .mounts(with_namespace!(req, ns)) + .await? + .into_inner() + .mounts; + drop(sc); + let mut tc = c.tasks(); let req = CreateTaskRequest { - container_id: container_id.clone(), - stdin: stdin.to_str().unwrap().to_string(), - stdout: stdout.to_str().unwrap().to_string(), - stderr: stderr.to_str().unwrap().to_string(), + container_id: cid.to_string(), + rootfs: mounts, ..Default::default() }; - let req = with_namespace!(req, NAMESPACE); + let _resp = tc.create(with_namespace!(req, ns)).await?; - let _resp = tasks_client - .create(req) - .await - .expect("Failed to create task"); - - println!("Task: {:?} created", container_id); - - let req = StartRequest { - container_id: container_id.to_string(), - ..Default::default() - }; - let req = with_namespace!(req, NAMESPACE); - - let _resp = tasks_client.start(req).await.expect("Failed to start task"); - - println!("Task: {:?} started", container_id); + Ok(()) } - pub async fn kill_task(&self, container_id: String) { - let mut tasks_client = self.client.lock().unwrap().tasks(); - let kill_request = Request::new(KillRequest { - container_id: container_id.to_string(), + async fn start_task(&self, cid: &str, ns: &str) -> Result<(), Err> { + let req = StartRequest { + container_id: cid.to_string(), + ..Default::default() + }; + let _resp = self + .client + .lock() + .unwrap() + .tasks() + .start(with_namespace!(req, ns)) + .await?; + + Ok(()) + } + + pub async fn kill_task(&self, cid: String, ns: &str) -> Result<(), Err> { + let namespace = match ns { + "" => NAMESPACE, + _ => ns, + }; + let mut c = self.client.lock().unwrap().tasks(); + let kill_request = KillRequest { + container_id: cid.to_string(), signal: 15, all: true, ..Default::default() - }); - tasks_client - .kill(kill_request) + }; + c.kill(with_namespace!(kill_request, namespace)) .await .expect("Failed to kill task"); + + Ok(()) } pub async fn pause_task() { todo!() @@ -184,62 +263,74 @@ impl Service { pub async fn resume_task() { todo!() } - pub async fn delete_task(&self, container_id: &str) { + pub async fn delete_task(&self, cid: &str, ns: &str) { + let namespace = match ns { + "" => NAMESPACE, + _ => ns, + }; + let mut c = self.client.lock().unwrap().tasks(); let time_out = Duration::from_secs(30); - let mut tc = self.client.lock().unwrap().tasks(); let wait_result = timeout(time_out, async { - let wait_request = Request::new(WaitRequest { - container_id: container_id.to_string(), + let wait_request = WaitRequest { + container_id: cid.to_string(), ..Default::default() - }); + }; - let _ = tc.wait(wait_request).await?; + let _ = c.wait(with_namespace!(wait_request, namespace)).await?; Ok::<(), Err>(()) }) .await; - let kill_request = Request::new(KillRequest { - container_id: container_id.to_string(), + let kill_request = KillRequest { + container_id: cid.to_string(), signal: 15, all: true, ..Default::default() - }); - tc.kill(kill_request).await.expect("Failed to kill task"); + }; + c.kill(with_namespace!(kill_request, namespace)) + .await + .expect("Failed to kill task"); match wait_result { Ok(Ok(_)) => { let req = DeleteTaskRequest { - container_id: container_id.to_string(), + container_id: cid.to_string(), }; - let req = with_namespace!(req, NAMESPACE); - let _resp = tc.delete(req).await.expect("Failed to delete task"); - println!("Task: {:?} deleted", container_id); + let _resp = c + .delete(with_namespace!(req, namespace)) + .await + .expect("Failed to delete task"); + println!("Task: {:?} deleted", cid); } _ => { - let kill_request = Request::new(KillRequest { - container_id: container_id.to_string(), + let kill_request = KillRequest { + container_id: cid.to_string(), signal: 9, all: true, ..Default::default() - }); - tc.kill(kill_request) + }; + c.kill(with_namespace!(kill_request, namespace)) .await .expect("Failed to FORCE kill task"); } } } - pub async fn get_container_list(&self) -> Result, tonic::Status> { - let mut cc = self.client.lock().unwrap().containers(); + pub async fn get_container_list(&self, ns: &str) -> Result, tonic::Status> { + let namespace = match ns { + "" => NAMESPACE, + _ => ns, + }; + let mut c = self.client.lock().unwrap().containers(); let request = ListContainersRequest { ..Default::default() }; - let request = with_namespace!(request, NAMESPACE); + let request = with_namespace!(request, namespace); - let response = cc.list(request).await?; + let response = c.list(request).await?; Ok(response .into_inner() @@ -249,7 +340,9 @@ impl Service { .collect()) } - pub async fn get_task_list() {} + pub async fn get_task_list() { + todo!() + } pub fn prepare_image(&self) { todo!() @@ -261,6 +354,174 @@ impl Service { pub fn get_resolver(&self) { todo!() } + + async fn handle_index(&self, data: &Vec, ns: &str) -> Option { + let image_index: ImageIndex = ::serde_json::from_slice(&data).unwrap(); + let img_manifest_dscr = image_index + .manifests() + .iter() + .find(|manifest_entry| match manifest_entry.platform() { + Some(p) => { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + { + matches!(p.architecture(), &Arch::Amd64) && matches!(p.os(), &Os::Linux) + } + #[cfg(target_arch = "aarch64")] + { + matches!(p.architecture(), &Arch::ARM64) && matches!(p.os(), Os::Linux) + //&& matches!(p.variant().as_ref().map(|s| s.as_str()), Some("v8")) + } + } + None => false, + }) + .unwrap(); + + let req = ReadContentRequest { + digest: img_manifest_dscr.digest().to_owned(), + offset: 0, + size: 0, + }; + + let mut c = self.client.lock().unwrap().content(); + let resp = c + .read(with_namespace!(req, ns)) + .await + .expect("Failed to read content") + .into_inner() + .message() + .await + .expect("Failed to read content message") + .unwrap() + .data; + + self.handle_manifest(&resp, ns).await + } + + async fn handle_manifest(&self, data: &Vec, ns: &str) -> Option { + let img_manifest: ImageManifest = ::serde_json::from_slice(&data).unwrap(); + let img_manifest_dscr = img_manifest.config(); + + let req = ReadContentRequest { + digest: img_manifest_dscr.digest().to_owned(), + offset: 0, + size: 0, + }; + let mut c = self.client.lock().unwrap().content(); + + let resp = c + .read(with_namespace!(req, ns)) + .await + .unwrap() + .into_inner() + .message() + .await + .unwrap() + .unwrap() + .data; + + ::serde_json::from_slice(&resp).unwrap() + } + + pub async fn get_img_config(&self, name: &str, ns: &str) -> Option { + let mut c = self.client.lock().unwrap().images(); + + let req = GetImageRequest { + name: name.to_string(), + }; + let resp = c + .get(with_namespace!(req, ns)) + .await + .map_err(|e| { + eprintln!( + "Failed to get the config of {} in namespace {}: {}", + name, ns, e + ); + e + }) + .ok()? + .into_inner(); + + let img_dscr = resp.image?.target?; + let media_type = MediaType::from(img_dscr.media_type.as_str()); + + let req = ReadContentRequest { + digest: img_dscr.digest, + ..Default::default() + }; + + let mut c = self.client.lock().unwrap().content(); + + let resp = c + .read(with_namespace!(req, ns)) + .await + .map_err(|e| { + eprintln!( + "Failed to read content for {} in namespace {}: {}", + name, ns, e + ); + e + }) + .ok()? + .into_inner() + .message() + .await + .map_err(|e| { + eprintln!( + "Failed to read message for {} in namespace {}: {}", + name, ns, e + ); + e + }) + .ok()? + .ok_or_else(|| { + eprintln!("No data found for {} in namespace {}", name, ns); + std::io::Error::new(std::io::ErrorKind::NotFound, "No data found") + }) + .ok()? + .data; + + let img_config = match media_type { + MediaType::ImageIndex => self.handle_index(&resp, ns).await.unwrap(), + MediaType::ImageManifest => self.handle_manifest(&resp, ns).await.unwrap(), + MediaType::Other(media_type) => match media_type.as_str() { + "application/vnd.docker.distribution.manifest.list.v2+json" => { + self.handle_index(&resp, ns).await.unwrap() + } + "application/vnd.docker.distribution.manifest.v2+json" => { + self.handle_manifest(&resp, ns).await.unwrap() + } + _ => { + eprintln!("Unexpected media type '{}'", media_type); + return None; + } + }, + _ => { + eprintln!("Unexpected media type '{}'", media_type); + return None; + } + }; + Some(img_config) + } + + async fn get_parent_snapshot(&self, name: &str, ns: &str) -> Result { + let img_config = self.get_img_config(name, ns).await.unwrap(); + + let mut iter = img_config.rootfs().diff_ids().iter(); + let mut ret = iter + .next() + .map_or_else(String::new, |layer_digest| layer_digest.clone()); + + while let Some(layer_digest) = iter.next() { + let mut hasher = Sha256::new(); + hasher.update(ret.as_bytes()); + ret.push_str(&format!(",{}", layer_digest)); + hasher.update(" "); + hasher.update(layer_digest); + let digest = ::hex::encode(hasher.finalize()); + ret = format!("sha256:{digest}"); + } + Ok(ret) + } } //容器是容器,要先启动,然后才能运行任务 //要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。 diff --git a/service/src/spec.rs b/service/src/spec.rs index 0cc482b..6469009 100644 --- a/service/src/spec.rs +++ b/service/src/spec.rs @@ -9,95 +9,100 @@ const VERSION_DEV: &str = ""; // 对应开发分支 const RWM: &str = "rwm"; const DEFAULT_ROOTFS_PATH: &str = "rootfs"; +pub const DEFAULT_NAMESPACE: &str = "default"; +const PATH_TO_SPEC_PREFIX: &str = "/tmp/containerd-spec"; -const DEFAULT_UNIX_ENV:&str="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; +// const DEFAULT_UNIX_ENV: &str = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; const PID_NAMESPACE: &str = "pid"; const NETWORK_NAMESPACE: &str = "network"; const MOUNT_NAMESPACE: &str = "mount"; const IPC_NAMESPACE: &str = "ipc"; const UTS_NAMESPACE: &str = "uts"; -const USER_NAMESPACE: &str = "user"; -const CGROUP_NAMESPACE: &str = "cgroup"; -const TIME_NAMESPACE: &str = "time"; - #[derive(Serialize, Deserialize, Debug)] -struct Spec { - ociVersion: String, - root: Root, - process: Process, - linux: Linux, - mounts: Vec, +pub struct Spec { + #[serde(rename = "ociVersion")] + pub oci_version: String, + pub root: Root, + pub process: Process, + pub linux: Linux, + pub mounts: Vec, } #[derive(Serialize, Deserialize, Debug)] -struct Root { - path: String, +pub struct Root { + pub path: String, } #[derive(Serialize, Deserialize, Debug)] -struct Process { - cwd: String, - noNewPrivileges: bool, - user: User, - capabilities: LinuxCapabilities, - rlimits: Vec, +pub struct Process { + pub cwd: String, + #[serde(rename = "noNewPrivileges")] + pub no_new_privileges: bool, + pub user: User, + pub capabilities: LinuxCapabilities, + pub rlimits: Vec, + pub args: Vec, + pub env: Vec, } #[derive(Serialize, Deserialize, Debug)] -struct User { - uid: u32, - gid: u32, +pub struct User { + pub uid: u32, + pub gid: u32, + #[serde(rename = "additionalGids")] + pub additional_gids: Vec, } #[derive(Serialize, Deserialize, Debug)] -struct Mount { - destination: String, - type_: String, - source: String, - options: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -struct LinuxCapabilities { - bounding: Vec, - permitted: Vec, - effective: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -struct POSIXRlimit { +pub struct Mount { + pub destination: String, #[serde(rename = "type")] - type_: String, - hard: u64, - soft: u64, + pub type_: String, + pub source: String, + pub options: Vec, } #[derive(Serialize, Deserialize, Debug)] -struct Linux { - masked_paths: Vec, - readonly_paths: Vec, - cgroups_path: String, - resources: LinuxResources, - namespaces: Vec, +pub struct LinuxCapabilities { + pub bounding: Vec, + pub permitted: Vec, + pub effective: Vec, } #[derive(Serialize, Deserialize, Debug)] -struct LinuxResources { - devices: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -struct LinuxDeviceCgroup { - allow: bool, - access: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct LinuxNamespace { +pub struct POSIXRlimit { + pub hard: u64, + pub soft: u64, #[serde(rename = "type")] - type_: String, + pub type_: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Linux { + pub masked_paths: Vec, + pub readonly_paths: Vec, + pub cgroups_path: String, + pub resources: LinuxResources, + pub namespaces: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct LinuxResources { + pub devices: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct LinuxDeviceCgroup { + pub allow: bool, + pub access: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct LinuxNamespace { + #[serde(rename = "type")] + pub type_: String, } pub fn default_unix_caps() -> Vec { @@ -252,16 +257,20 @@ fn get_version() -> String { ) } -fn populate_default_unix_spec(id: &str, ns: &str) -> Spec { +pub fn populate_default_unix_spec(id: &str, ns: &str) -> Spec { Spec { - ociVersion: get_version(), + oci_version: get_version(), root: Root { path: DEFAULT_ROOTFS_PATH.to_string(), }, process: Process { cwd: String::from("/"), - noNewPrivileges: true, - user: User { uid: 0, gid: 0 }, + no_new_privileges: true, + user: User { + uid: 0, + gid: 0, + additional_gids: vec![], + }, capabilities: LinuxCapabilities { bounding: default_unix_caps(), permitted: default_unix_caps(), @@ -272,6 +281,8 @@ fn populate_default_unix_spec(id: &str, ns: &str) -> Spec { hard: 1024, soft: 1024, }], + args: vec![], + env: vec![], }, linux: Linux { masked_paths: default_masked_parhs(), @@ -280,7 +291,7 @@ fn populate_default_unix_spec(id: &str, ns: &str) -> Spec { resources: LinuxResources { devices: vec![LinuxDeviceCgroup { allow: false, - access: String::from("rwm"), + access: RWM.to_string(), }], }, namespaces: default_unix_namespaces(), @@ -289,9 +300,19 @@ fn populate_default_unix_spec(id: &str, ns: &str) -> Spec { } } -fn save_spec_to_file(spec: &Spec, path: &str) -> Result<(), std::io::Error> { +pub fn save_spec_to_file(spec: &Spec, path: &str) -> Result<(), std::io::Error> { let file = File::create(path)?; serde_json::to_writer(file, spec)?; Ok(()) } +pub fn generate_spec(id: &str, ns: &str) -> Result { + let namespace = match ns { + "" => DEFAULT_NAMESPACE, + _ => ns, + }; + let spec = populate_default_unix_spec(id, ns); + let path = format!("{}/{}/{}.json", PATH_TO_SPEC_PREFIX, namespace, id); + save_spec_to_file(&spec, &path)?; + Ok(path) +} From eee53e6c73ba75c42ebd1fb953d127ea1bbea664 Mon Sep 17 00:00:00 2001 From: sparkzky Date: Thu, 27 Feb 2025 21:33:50 +0800 Subject: [PATCH 3/6] 1 --- Cargo.lock | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index dde0ccc..578d29a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -502,6 +502,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.3.11" @@ -511,6 +546,37 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -686,6 +752,18 @@ dependencies = [ "wasi", ] +[[package]] +name = "getset" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded738faa0e88d3abc9d1a13cb11adc2073c400969eeb8793cf7132589959fc" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "gimli" version = "0.31.1" @@ -754,6 +832,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "http" version = "0.2.12" @@ -988,6 +1072,12 @@ dependencies = [ "syn", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -1187,6 +1277,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "oci-spec" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf88ddc01cc6bccbe1044adb6a29057333f523deadcb4953c011a73158cfa5e" +dependencies = [ + "derive_builder", + "getset", + "serde", + "serde_json", + "strum", + "strum_macros", + "thiserror", +] + [[package]] name = "once_cell" version = "1.20.2" @@ -1301,6 +1406,28 @@ dependencies = [ "syn", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.93" @@ -1547,10 +1674,13 @@ version = "0.1.0" dependencies = [ "containerd-client", "env_logger", + "hex", "log", + "oci-spec", "prost-types", "serde", "serde_json", + "sha2", "tokio", "tonic", ] @@ -1566,6 +1696,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1612,6 +1753,31 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "2.0.96" @@ -1663,6 +1829,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.3.37" From caa05b93fc7584f020face6eda3265ebde712231 Mon Sep 17 00:00:00 2001 From: sparkzky Date: Thu, 27 Feb 2025 22:00:32 +0800 Subject: [PATCH 4/6] remove container_spec.json --- crates/service/container_spec.json | 158 ----------------------------- 1 file changed, 158 deletions(-) delete mode 100644 crates/service/container_spec.json diff --git a/crates/service/container_spec.json b/crates/service/container_spec.json deleted file mode 100644 index ea26e4f..0000000 --- a/crates/service/container_spec.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "ociVersion": "1.0.0-rc2-dev", - "platform": { - "os": "linux", - "arch": "amd64" - }, - "process": { - "terminal": false, - "consoleSize": { - "height": 0, - "width": 0 - }, - "user": { - "uid": 0, - "gid": 0 - }, - "args": [ "echo", "$OUTPUT" ], - "env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "TERM=xterm" - ], - "cwd": "/", - "rlimits": [{ - "type": "RLIMIT_NOFILE", - "hard": 1024, - "soft": 1024 - }], - "noNewPrivileges": true - }, - "root": { - "path": "$ROOTFS", - "readonly": false - }, - "hostname": "test", - "mounts": [{ - "destination": "/proc", - "type": "proc", - "source": "proc" - }, - { - "destination": "/dev", - "type": "tmpfs", - "source": "tmpfs", - "options": [ - "nosuid", - "strictatime", - "mode=755", - "size=65536k" - ] - }, - { - "destination": "/dev/pts", - "type": "devpts", - "source": "devpts", - "options": [ - "nosuid", - "noexec", - "newinstance", - "ptmxmode=0666", - "mode=0620", - "gid=5" - ] - }, - { - "destination": "/dev/shm", - "type": "tmpfs", - "source": "shm", - "options": [ - "nosuid", - "noexec", - "nodev", - "mode=1777", - "size=65536k" - ] - }, - { - "destination": "/dev/mqueue", - "type": "mqueue", - "source": "mqueue", - "options": [ - "nosuid", - "noexec", - "nodev" - ] - }, - { - "destination": "/sys", - "type": "sysfs", - "source": "sysfs", - "options": [ - "nosuid", - "noexec", - "nodev", - "ro" - ] - }, - { - "destination": "/sys/fs/cgroup", - "type": "cgroup", - "source": "cgroup", - "options": [ - "nosuid", - "noexec", - "nodev", - "relatime", - "ro" - ] - } - ], - "hooks": {}, - "linux": { - "devices": [], - "cgroupsPath": "kata/vfiotest", - "resources": { - "devices": [ - {"allow":false,"access":"rwm"}, - {"allow":true,"type":"c","major":1,"minor":3,"access":"rwm"}, - {"allow":true,"type":"c","major":1,"minor":5,"access":"rwm"}, - {"allow":true,"type":"c","major":1,"minor":8,"access":"rwm"}, - {"allow":true,"type":"c","major":1,"minor":9,"access":"rwm"}, - {"allow":true,"type":"c","major":5,"minor":0,"access":"rwm"}, - {"allow":true,"type":"c","major":5,"minor":1,"access":"rwm"} - ] - }, - "namespaces": [{ - "type": "pid" - }, - { - "type": "network" - }, - { - "type": "ipc" - }, - { - "type": "uts" - }, - { - "type": "mount" - } - ], - "maskedPaths": [ - "/proc/kcore", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/sys/firmware" - ], - "readonlyPaths": [ - "/proc/asound", - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger" - ] - } -} \ No newline at end of file From 377d649d4ee572beffc8ecafd22a5c3673964bfc Mon Sep 17 00:00:00 2001 From: sparkzky Date: Thu, 27 Feb 2025 22:26:45 +0800 Subject: [PATCH 5/6] 1 --- crates/app/src/handlers.rs | 4 ++-- crates/app/src/main.rs | 4 ++-- crates/app/src/types.rs | 2 +- crates/service/src/lib.rs | 14 +------------- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/crates/app/src/handlers.rs b/crates/app/src/handlers.rs index 14b0631..f1c7596 100644 --- a/crates/app/src/handlers.rs +++ b/crates/app/src/handlers.rs @@ -1,5 +1,5 @@ use crate::types::*; -use actix_web::{HttpResponse, Responder, web}; +use actix_web::{web, HttpResponse, Responder}; use service::Service; use std::sync::Arc; @@ -36,4 +36,4 @@ pub async fn get_container_list( HttpResponse::Ok().json(container_list) } -// 添加更多的路由处理函数... +// 添加更多的路由处理函数... \ No newline at end of file diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 3669bcb..b1216ef 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use actix_web::{App, HttpServer, web}; +use actix_web::{web, App, HttpServer}; use service::Service; pub mod handlers; @@ -29,4 +29,4 @@ async fn main() -> std::io::Result<()> { .bind("0.0.0.0:18080")? .run() .await -} +} \ No newline at end of file diff --git a/crates/app/src/types.rs b/crates/app/src/types.rs index 9b843e6..0d92a7e 100644 --- a/crates/app/src/types.rs +++ b/crates/app/src/types.rs @@ -17,4 +17,4 @@ pub struct RemoveContainerInfo { pub struct GetContainerListQuery { pub status: Option, pub ns: String, -} +} \ No newline at end of file diff --git a/crates/service/src/lib.rs b/crates/service/src/lib.rs index 71f7b8f..dfb5304 100644 --- a/crates/service/src/lib.rs +++ b/crates/service/src/lib.rs @@ -1,7 +1,6 @@ pub mod spec; use containerd_client::{ - Client, services::v1::{ container::Runtime, snapshots::{MountsRequest, PrepareSnapshotRequest}, @@ -19,16 +18,6 @@ use sha2::{Digest, Sha256}; use spec::generate_spec; use std::{ fs, - Container, CreateContainerRequest, CreateTaskRequest, DeleteContainerRequest, - DeleteTaskRequest, KillRequest, ListContainersRequest, ListTasksRequest, StartRequest, - WaitRequest, container::Runtime, - }, - tonic::Request, - with_namespace, -}; - -use std::{ - fs::{self, File}, sync::{Arc, Mutex}, time::Duration, }; @@ -36,7 +25,6 @@ use tokio::time::timeout; // config.json,dockerhub密钥 // const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/"; - // 命名空间(容器的) const NAMESPACE: &str = "default"; @@ -536,4 +524,4 @@ impl Service { } } //容器是容器,要先启动,然后才能运行任务 -//要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。 +//要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。 \ No newline at end of file From a04fd9b18569c6aea669569f21235ff9281bb768 Mon Sep 17 00:00:00 2001 From: sparkzky Date: Thu, 27 Feb 2025 22:34:50 +0800 Subject: [PATCH 6/6] fmt --- Cargo.lock | 2 +- crates/app/src/handlers.rs | 4 ++-- crates/app/src/main.rs | 4 ++-- crates/app/src/types.rs | 2 +- crates/service/src/lib.rs | 16 ++++++---------- crates/service/src/spec.rs | 2 +- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86b73cf..84abbb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1699,8 +1699,8 @@ dependencies = [ "env_logger", "hex", "log", - "oci-spec", "my-workspace-hack", + "oci-spec", "prost-types", "serde", "serde_json", diff --git a/crates/app/src/handlers.rs b/crates/app/src/handlers.rs index f1c7596..14b0631 100644 --- a/crates/app/src/handlers.rs +++ b/crates/app/src/handlers.rs @@ -1,5 +1,5 @@ use crate::types::*; -use actix_web::{web, HttpResponse, Responder}; +use actix_web::{HttpResponse, Responder, web}; use service::Service; use std::sync::Arc; @@ -36,4 +36,4 @@ pub async fn get_container_list( HttpResponse::Ok().json(container_list) } -// 添加更多的路由处理函数... \ No newline at end of file +// 添加更多的路由处理函数... diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index b1216ef..3669bcb 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use actix_web::{web, App, HttpServer}; +use actix_web::{App, HttpServer, web}; use service::Service; pub mod handlers; @@ -29,4 +29,4 @@ async fn main() -> std::io::Result<()> { .bind("0.0.0.0:18080")? .run() .await -} \ No newline at end of file +} diff --git a/crates/app/src/types.rs b/crates/app/src/types.rs index 0d92a7e..9b843e6 100644 --- a/crates/app/src/types.rs +++ b/crates/app/src/types.rs @@ -17,4 +17,4 @@ pub struct RemoveContainerInfo { pub struct GetContainerListQuery { pub status: Option, pub ns: String, -} \ No newline at end of file +} diff --git a/crates/service/src/lib.rs b/crates/service/src/lib.rs index dfb5304..71cf96a 100644 --- a/crates/service/src/lib.rs +++ b/crates/service/src/lib.rs @@ -1,16 +1,17 @@ pub mod spec; use containerd_client::{ + Client, services::v1::{ - container::Runtime, - snapshots::{MountsRequest, PrepareSnapshotRequest}, Container, CreateContainerRequest, CreateTaskRequest, DeleteContainerRequest, DeleteTaskRequest, GetImageRequest, KillRequest, ListContainersRequest, ListTasksRequest, ReadContentRequest, StartRequest, WaitRequest, + container::Runtime, + snapshots::{MountsRequest, PrepareSnapshotRequest}, }, tonic::Request, types::Mount, - with_namespace, Client, + with_namespace, }; use oci_spec::image::{Arch, ImageConfiguration, ImageIndex, ImageManifest, MediaType, Os}; use prost_types::Any; @@ -63,12 +64,7 @@ impl Service { Ok(resp) } - pub async fn create_container( - &self, - image_name: &str, - cid: &str, - ns: &str, - ) -> Result<(), Err> { + pub async fn create_container(&self, image_name: &str, cid: &str, ns: &str) -> Result<(), Err> { let namespace = match ns { "" => spec::DEFAULT_NAMESPACE, _ => ns, @@ -524,4 +520,4 @@ impl Service { } } //容器是容器,要先启动,然后才能运行任务 -//要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。 \ No newline at end of file +//要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。 diff --git a/crates/service/src/spec.rs b/crates/service/src/spec.rs index 65394eb..6469009 100644 --- a/crates/service/src/spec.rs +++ b/crates/service/src/spec.rs @@ -315,4 +315,4 @@ pub fn generate_spec(id: &str, ns: &str) -> Result { let path = format!("{}/{}/{}.json", PATH_TO_SPEC_PREFIX, namespace, id); save_spec_to_file(&spec, &path)?; Ok(path) -} \ No newline at end of file +}