···6969 serve Start fireup HTTP API server
7070 inspect Inspect the Firecracker MicroVM details
7171 exec Execute a command inside the Firecracker MicroVM
7272+ cp Copy files to/from the Firecracker MicroVM
7273 help Print this message or the help of the given subcommand(s)
73747475Options:
+77
crates/firecracker-up/src/cmd/cp.rs
···11+use anyhow::Error;
22+use owo_colors::OwoColorize;
1344+use crate::{command::run_command_with_stdout_inherit, ssh::get_private_key_path};
55+66+pub async fn cp(from: &str, to: &str) -> Result<(), Error> {
77+ let pool = firecracker_state::create_connection_pool().await?;
88+99+ let vm_name = if from.contains(':') {
1010+ from.split(':').next().unwrap_or("")
1111+ } else if to.contains(':') {
1212+ to.split(':').next().unwrap_or("")
1313+ } else {
1414+ return Err(anyhow::anyhow!(
1515+ "Either source or destination must be in the format <vm_name>:<path>"
1616+ ));
1717+ };
1818+1919+ let vm = firecracker_state::repo::virtual_machine::find(&pool, vm_name).await?;
2020+2121+ if vm.is_none() {
2222+ println!("[-] MicroVM '{}' not found.", vm_name);
2323+ std::process::exit(1);
2424+ }
2525+2626+ if !firecracker_process::vm_is_running(vm_name).await? {
2727+ println!("[-] MicroVM '{}' is not running.", vm_name);
2828+ let start_cmd = format!("fireup start {}", vm_name);
2929+ println!(" Start it with {}", start_cmd.cyan());
3030+ std::process::exit(1);
3131+ }
3232+3333+ let guest_ip = format!("{}.firecracker", vm_name);
3434+ let key_path = get_private_key_path()?;
3535+3636+ let scp_args = if from.contains(':') {
3737+ let remote_path = format!(
3838+ "root@{}:{}",
3939+ guest_ip,
4040+ from.splitn(2, ':').nth(1).unwrap()
4141+ );
4242+ vec!["-r", remote_path.as_str(), to]
4343+ .iter()
4444+ .map(|s| s.to_string())
4545+ .collect::<Vec<String>>()
4646+ } else {
4747+ let remote_path = format!(
4848+ "root@{}:{}",
4949+ guest_ip,
5050+ to.splitn(2, ':').nth(1).unwrap()
5151+ );
5252+ vec!["-r", from, remote_path.as_str()]
5353+ .iter()
5454+ .map(|s| s.to_string())
5555+ .collect::<Vec<String>>()
5656+ };
5757+5858+ run_command_with_stdout_inherit(
5959+ "scp",
6060+ &[
6161+ "-q",
6262+ "-i",
6363+ &key_path,
6464+ "-o",
6565+ "StrictHostKeyChecking=no",
6666+ "-o",
6767+ "UserKnownHostsFile=/dev/null",
6868+ ]
6969+ .iter()
7070+ .copied()
7171+ .chain(scp_args.iter().map(|s| s.as_str()))
7272+ .collect::<Vec<&str>>()
7373+ .as_slice(),
7474+ false,
7575+ )?;
7676+7777+ Ok(())
7878+}
+2-23
crates/firecracker-up/src/cmd/exec.rs
···11-use anyhow::{anyhow, Context, Error, Result};
11+use anyhow::{Error, Result};
22use firecracker_state::repo;
33use owo_colors::OwoColorize;
44-use std::fs;
5466-use crate::command::run_ssh_command;
55+use crate::{command::run_ssh_command, ssh::get_private_key_path};
7687pub async fn exec(name: &str, args: Vec<String>) -> Result<(), Error> {
98 let pool = firecracker_state::create_connection_pool().await?;
···26252726 Ok(())
2827}
2929-3030-fn get_private_key_path() -> Result<String, Error> {
3131- let home_dir = dirs::home_dir().ok_or_else(|| anyhow!("Failed to get home directory"))?;
3232- let app_dir = format!("{}/.fireup", home_dir.display());
3333- let key_name = glob::glob(format!("{}/id_rsa", app_dir).as_str())
3434- .with_context(|| "Failed to glob ssh key files")?
3535- .last()
3636- .ok_or_else(|| anyhow!("No SSH key file found"))?
3737- .with_context(|| "Failed to get SSH key path")?;
3838- let key_name = fs::canonicalize(&key_name)
3939- .with_context(|| {
4040- format!(
4141- "Failed to resolve absolute path for SSH key: {}",
4242- key_name.display()
4343- )
4444- })?
4545- .display()
4646- .to_string();
4747- Ok(key_name)
4848-}