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