Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization
linux
microvm
firecracker
1use anyhow::Error;
2use owo_colors::OwoColorize;
3
4use crate::{command::run_command_with_stdout_inherit, ssh::get_private_key_path};
5
6pub async fn cp(from: &str, to: &str) -> Result<(), Error> {
7 let pool = firecracker_state::create_connection_pool().await?;
8
9 let vm_name = if from.contains(':') {
10 from.split(':').next().unwrap_or("")
11 } else if to.contains(':') {
12 to.split(':').next().unwrap_or("")
13 } else {
14 return Err(anyhow::anyhow!(
15 "Either source or destination must be in the format <vm_name>:<path>"
16 ));
17 };
18
19 let vm = firecracker_state::repo::virtual_machine::find(&pool, vm_name).await?;
20
21 if vm.is_none() {
22 println!("[-] MicroVM '{}' not found.", vm_name);
23 std::process::exit(1);
24 }
25
26 if !firecracker_process::vm_is_running(vm_name).await? {
27 println!("[-] MicroVM '{}' is not running.", vm_name);
28 let start_cmd = format!("fireup start {}", vm_name);
29 println!(" Start it with {}", start_cmd.cyan());
30 std::process::exit(1);
31 }
32
33 let guest_ip = format!("{}.firecracker", vm_name);
34 let key_path = get_private_key_path()?;
35
36 let scp_args = if from.contains(':') {
37 let remote_path = format!("root@{}:{}", guest_ip, from.splitn(2, ':').nth(1).unwrap());
38 vec!["-r", remote_path.as_str(), to]
39 .iter()
40 .map(|s| s.to_string())
41 .collect::<Vec<String>>()
42 } else {
43 let remote_path = format!("root@{}:{}", guest_ip, to.splitn(2, ':').nth(1).unwrap());
44 vec!["-r", from, remote_path.as_str()]
45 .iter()
46 .map(|s| s.to_string())
47 .collect::<Vec<String>>()
48 };
49
50 run_command_with_stdout_inherit(
51 "scp",
52 &[
53 "-q",
54 "-i",
55 &key_path,
56 "-o",
57 "StrictHostKeyChecking=no",
58 "-o",
59 "UserKnownHostsFile=/dev/null",
60 ]
61 .iter()
62 .copied()
63 .chain(scp_args.iter().map(|s| s.as_str()))
64 .collect::<Vec<&str>>()
65 .as_slice(),
66 false,
67 )?;
68
69 Ok(())
70}