1 // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 // 3 // StratoVirt is licensed under Mulan PSL v2. 4 // You can use this software according to the terms and conditions of the Mulan 5 // PSL v2. 6 // You may obtain a copy of Mulan PSL v2 at: 7 // http://license.coscl.org.cn/MulanPSL2 8 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 // See the Mulan PSL v2 for more details. 12 13 use std::path::{Path, PathBuf}; 14 15 use anyhow::{Context, Ok, Result}; 16 use clap::{builder::NonEmptyStringValueParser, Parser}; 17 18 use crate::container::{Action, Container, Launcher}; 19 use crate::linux::LinuxContainer; 20 use oci_spec::runtime::RuntimeConfig; 21 22 /// Create a container from a bundle directory 23 #[derive(Parser, Debug)] 24 pub struct Create { 25 /// File to write the container PID to 26 #[arg(short, long)] 27 pub pid_file: Option<PathBuf>, 28 /// Path to the bundle directory, defaults to the current working directory. 29 #[arg(short, long, default_value = ".")] 30 pub bundle: PathBuf, 31 /// Path to an AF_UNIX socket which will receive the pseudoterminal master 32 /// at a file descriptor. 33 #[arg(short, long)] 34 pub console_socket: Option<PathBuf>, 35 /// Container ID to create. 36 #[arg(value_parser = NonEmptyStringValueParser::new(), required = true)] 37 pub container_id: String, 38 } 39 40 impl Create { launcher(&self, root: &Path, exist: &mut bool) -> Result<Launcher>41 fn launcher(&self, root: &Path, exist: &mut bool) -> Result<Launcher> { 42 let bundle_path = self 43 .bundle 44 .canonicalize() 45 .with_context(|| "Failed to canonicalize bundle path")?; 46 let config_path = bundle_path 47 .join("config.json") 48 .to_string_lossy() 49 .to_string(); 50 let mut config = RuntimeConfig::from_file(&config_path)?; 51 let mut rootfs_path = PathBuf::from(config.root.path); 52 53 if !rootfs_path.is_absolute() { 54 rootfs_path = bundle_path.join(rootfs_path); 55 } 56 config.root.path = rootfs_path.to_string_lossy().to_string(); 57 58 let container: Box<dyn Container> = Box::new(LinuxContainer::new( 59 &self.container_id, 60 &root.to_string_lossy().to_string(), 61 &config, 62 &self.console_socket, 63 exist, 64 )?); 65 Ok(Launcher::new( 66 &bundle_path, 67 root, 68 true, 69 container, 70 self.pid_file.clone(), 71 )) 72 } 73 run(&self, root: &Path, exist: &mut bool) -> Result<()>74 pub fn run(&self, root: &Path, exist: &mut bool) -> Result<()> { 75 let mut launcher = self.launcher(root, exist)?; 76 launcher.launch(Action::Create)?; 77 Ok(()) 78 } 79 } 80