Skip to main content

docker_config/
runtime.rs

1#![warn(missing_docs)]
2
3//! 容器运行时
4
5use std::sync::Arc;
6use std::time::SystemTime;
7use tokio::sync::RwLock;
8use uuid::Uuid;
9
10use docker_types::{ContainerConfig, ContainerInfo, ContainerStatus, DockerConfig, DockerError};
11
12/// 结果类型
13pub type Result<T> = std::result::Result<T, DockerError>;
14
15/// 容器运行时
16pub struct ContainerRuntime {
17    /// 全局配置
18    config: Arc<DockerConfig>,
19    /// 容器列表
20    containers: Arc<RwLock<Vec<ContainerInfo>>>,
21}
22
23impl ContainerRuntime {
24    /// 创建新的容器运行时
25    pub fn new() -> Result<Self> {
26        // 使用默认配置
27        let default_config = DockerConfig {
28            data_dir: "./data".to_string(),
29            image_dir: "./data/images".to_string(),
30            container_dir: "./data/containers".to_string(),
31            network_dir: "./data/networks".to_string(),
32            default_network: "default".to_string(),
33            default_resources: docker_types::ResourceLimits {
34                cpu_limit: 1.0,
35                memory_limit: 512,
36                storage_limit: 10,
37                network_limit: 10,
38            },
39            log_config: docker_types::LogConfig {
40                log_level: "info".to_string(),
41                log_file: "./data/logs/docker.log".to_string(),
42                max_log_size: 100,
43            },
44        };
45
46        Ok(Self {
47            config: Arc::new(default_config),
48            containers: Arc::new(RwLock::new(vec![])),
49        })
50    }
51
52    /// 使用配置创建新的容器运行时
53    pub fn new_with_config(config: Arc<DockerConfig>) -> Result<Self> {
54        Ok(Self {
55            config,
56            containers: Arc::new(RwLock::new(vec![])),
57        })
58    }
59
60    /// 获取配置
61    pub fn get_config(&self) -> Arc<DockerConfig> {
62        self.config.clone()
63    }
64
65    /// 启动运行时
66    pub async fn start(&self) {
67        // 启动清理任务
68        tokio::spawn(async move {
69            // 定期清理停止的容器
70            loop {
71                tokio::time::sleep(tokio::time::Duration::from_mins(5)).await;
72                // 清理逻辑
73            }
74        });
75    }
76
77    /// 创建容器
78    pub async fn create_container(&self, config: ContainerConfig) -> Result<ContainerInfo> {
79        // 生成容器 ID
80        let container_id = Uuid::new_v4().to_string();
81
82        // 创建容器信息
83        let container_info = ContainerInfo {
84            id: container_id.clone(),
85            name: config.name.clone(),
86            image: config.image.clone(),
87            status: ContainerStatus::Creating,
88            config,
89            created_at: SystemTime::now(),
90            started_at: None,
91            stopped_at: None,
92            pid: None,
93            network_info: docker_types::NetworkInfo {
94                ip_address: None,
95                ports: Default::default(),
96                network_name: self.config.default_network.clone(),
97            },
98        };
99
100        // 添加到容器列表
101        let mut containers = self.containers.write().await;
102        containers.push(container_info.clone());
103
104        Ok(container_info)
105    }
106
107    /// 启动容器
108    pub async fn start_container(&self, container_id: &str) -> Result<()> {
109        let mut containers = self.containers.write().await;
110
111        if let Some(container) = containers.iter_mut().find(|c| c.id == container_id) {
112            // 检查状态
113            if container.status != ContainerStatus::Creating
114                && container.status != ContainerStatus::Stopped
115            {
116                return Err(DockerError::container_error(
117                    "Container is not in a state to start".to_string(),
118                ));
119            }
120
121            // 启动容器(这里是简化实现)
122            // 实际实现需要:
123            // 1. 进入命名空间
124            // 2. 挂载文件系统
125            // 3. 执行容器命令
126            // 4. 将进程添加到控制组
127
128            // 模拟启动
129            container.status = ContainerStatus::Running;
130            container.started_at = Some(SystemTime::now());
131            container.pid = Some(12345); // 模拟 PID
132
133            Ok(())
134        } else {
135            Err(DockerError::not_found(
136                "container",
137                format!("Container {} not found", container_id),
138            ))
139        }
140    }
141
142    /// 停止容器
143    pub async fn stop_container(&self, container_id: &str) -> Result<()> {
144        let mut containers = self.containers.write().await;
145
146        if let Some(container) = containers.iter_mut().find(|c| c.id == container_id) {
147            // 检查状态
148            if container.status != ContainerStatus::Running {
149                return Err(DockerError::container_error(
150                    "Container is not in a running state".to_string(),
151                ));
152            }
153
154            // 模拟停止
155            container.status = ContainerStatus::Stopped;
156            container.stopped_at = Some(SystemTime::now());
157            container.pid = None;
158
159            Ok(())
160        } else {
161            Err(DockerError::not_found(
162                "container",
163                format!("Container {} not found", container_id),
164            ))
165        }
166    }
167
168    /// 运行容器
169    pub async fn run_container(
170        &self,
171        image: String,
172        name: Option<String>,
173        _ports: Vec<String>,
174    ) -> Result<ContainerInfo> {
175        // 创建容器配置
176        let config = ContainerConfig {
177            name: name.unwrap_or_else(|| {
178                format!(
179                    "container-{}",
180                    Uuid::new_v4().to_string().split('-').next().unwrap()
181                )
182            }),
183            image,
184            command: vec!["/bin/sh".to_string()],
185            environment: Default::default(),
186            ports: Default::default(),
187            volumes: Default::default(),
188            resources: self.config.default_resources.clone(),
189            network: docker_types::NetworkConfig {
190                network_name: self.config.default_network.clone(),
191                static_ip: None,
192                hostname: None,
193                aliases: None,
194                network_mode: None,
195                enable_ipv6: false,
196            },
197            restart_policy: None,
198            healthcheck: None,
199            deploy: None,
200        };
201
202        // 创建并启动容器
203        let container_info = self.create_container(config).await?;
204        self.start_container(&container_info.id).await?;
205
206        Ok(container_info)
207    }
208
209    /// 列出容器
210    pub async fn list_containers(&self, all: bool) -> Result<Vec<ContainerInfo>> {
211        let containers = self.containers.read().await;
212
213        if all {
214            Ok(containers.clone())
215        } else {
216            Ok(containers
217                .iter()
218                .filter(|c| c.status == ContainerStatus::Running)
219                .cloned()
220                .collect())
221        }
222    }
223
224    /// 删除容器
225    pub async fn remove_container(&self, container_id: &str) -> Result<()> {
226        let mut containers = self.containers.write().await;
227
228        if let Some(index) = containers.iter().position(|c| c.id == container_id) {
229            // 检查状态
230            let container = &containers[index];
231            if container.status == ContainerStatus::Running {
232                return Err(DockerError::container_error(
233                    "Cannot remove a running container".to_string(),
234                ));
235            }
236
237            // 移除容器
238            containers.remove(index);
239
240            Ok(())
241        } else {
242            Err(DockerError::not_found(
243                "container",
244                format!("Container {} not found", container_id),
245            ))
246        }
247    }
248}