feat: implement VM command handling in snp module for enhanced CLI functionality

This commit is contained in:
Noor 2025-03-20 21:40:22 +05:30
parent daff2fd533
commit 30fc217ac3
Signed by: noormohammedb
GPG Key ID: D83EFB8B3B967146
3 changed files with 98 additions and 92 deletions

@ -1,6 +1,7 @@
use clap::{builder::PossibleValue, Arg, ArgMatches, Command}; use clap::{builder::PossibleValue, Arg, ArgMatches, Command};
use clap_complete::{generate, Shell}; use clap_complete::{generate, Shell};
use detee_cli::sgx::cli_handler::handle_app; use detee_cli::sgx::cli_handler::handle_app;
use detee_cli::snp::cli_handler::handle_vm;
use detee_cli::*; use detee_cli::*;
use std::error::Error; use std::error::Error;
use std::io; use std::io;
@ -598,98 +599,6 @@ fn handle_completion(matches: &ArgMatches, cmd: Command) {
} }
} }
fn handle_vm(matches: &ArgMatches) {
match matches.subcommand() {
Some(("deploy", args)) => cli_print(handle_vm_deploy(args)),
Some(("ssh", args)) => cli_print(handle_vm_ssh(args)),
Some(("list", args)) => cli_print(handle_vm_list(args)),
Some(("inspect", inspect_args)) => {
let uuid: String = inspect_args.get_one::<String>("uuid").unwrap().clone();
if *inspect_args.get_one::<bool>("show-node").unwrap() {
cli_print(snp::get_node_by_contract(&uuid).map_err(Into::into));
} else {
cli_print(snp::get_one_contract(&uuid).map_err(Into::into));
}
}
Some(("update", args)) => cli_print(handle_vm_update(args)),
Some(("delete", args)) => cli_print(handle_vm_delete(args)),
Some(("dtrfs", subcom_args)) => cli_print(handle_vm_dtrfs(subcom_args)),
Some(("distro", _)) => cli_print(Ok(crate::snp::Distro::get_template_list())),
_ => println!("No valid VM subcommand provided."),
}
}
fn handle_vm_deploy(matches: &ArgMatches) -> Result<snp::VmSshArgs, Box<dyn Error>> {
if let Some(path) = matches.get_one::<String>("yaml-path") {
return Ok(snp::deploy::Request::load_from_yaml(path)?);
}
let hostname = match matches.get_one::<String>("hostname") {
Some(hostname) => hostname.to_string(),
None => name_generator::random_vm_name(),
};
let location = matches.get_one::<String>("location").unwrap().as_str();
let ipv4: crate::snp::deploy::IPv4Config = match matches.get_one::<bool>("public-ip").unwrap() {
true => crate::snp::deploy::IPv4Config::PublicIPv4,
false => crate::snp::deploy::IPv4Config::PublishPorts(Vec::new()),
};
let distro =
crate::snp::Distro::from_string(matches.get_one::<String>("distribution").unwrap());
let vm_config = snp::deploy::Request {
hostname,
location: location.into(),
ipv4,
public_ipv6: false,
vcpus: *matches.get_one::<u32>("vcpus").unwrap(),
memory_mb: *matches.get_one::<u32>("memory").unwrap(),
disk_size_gb: *matches.get_one::<u32>("disk").unwrap(),
dtrfs: None,
hours: *matches.get_one::<u32>("hours").unwrap(),
price: *matches.get_one::<u64>("price").unwrap(),
distro: Some(distro),
};
Ok(vm_config.deploy()?)
}
fn handle_vm_update(update_vm_args: &ArgMatches) -> Result<SimpleOutput, Box<dyn Error>> {
let uuid = update_vm_args.get_one::<String>("uuid").unwrap().clone();
let memory = *update_vm_args.get_one::<u32>("memory").unwrap();
if memory > 0 && memory < 800 {
log::error!("At least 800MB of memory must be assgined to the VM");
return Ok(SimpleOutput::from(""));
}
snp::update::Request::process_request(
&uuid,
*update_vm_args.get_one::<u32>("vcpus").unwrap(),
memory,
*update_vm_args.get_one::<u32>("disk").unwrap(),
&update_vm_args.get_one::<String>("dtrfs").unwrap().to_string(),
)?;
let hours = *update_vm_args.get_one::<u32>("hours").unwrap();
if hours != 0 {
snp::update::expand_vm_hours(&uuid, hours)?;
}
Ok(SimpleOutput::from("VM successfully updated."))
}
fn handle_vm_list(update_vm_args: &ArgMatches) -> Result<Vec<snp::VmContract>, Box<dyn Error>> {
Ok(snp::list_contracts(*update_vm_args.get_one::<bool>("as-operator").unwrap())?)
}
fn handle_vm_ssh(ssh_args: &ArgMatches) -> Result<snp::VmSshArgs, Box<dyn Error>> {
let uuid: String = ssh_args.get_one::<String>("uuid").unwrap().clone();
Ok(snp::ssh(&uuid, *ssh_args.get_one::<bool>("just-print").unwrap())?)
}
fn handle_vm_delete(delete_args: &ArgMatches) -> Result<SimpleOutput, Box<dyn Error>> {
let uuid: String = delete_args.get_one::<String>("uuid").unwrap().clone();
snp::delete_contract(&uuid)?;
Ok(SimpleOutput::from("VM successfully deleted."))
}
fn handle_vm_dtrfs(_matches: &ArgMatches) -> Result<Vec<snp::Dtrfs>, Box<dyn Error>> {
Ok(crate::snp::Dtrfs::print_dtrfs_list())
}
fn handle_vm_nodes(matches: &ArgMatches) { fn handle_vm_nodes(matches: &ArgMatches) {
match matches.subcommand() { match matches.subcommand() {
Some(("search", _)) => cli_print(snp::print_nodes().map_err(Into::into)), Some(("search", _)) => cli_print(snp::print_nodes().map_err(Into::into)),

96
src/snp/cli_handler.rs Normal file

@ -0,0 +1,96 @@
use crate::name_generator;
use crate::snp;
use crate::{cli_print, SimpleOutput};
use clap::ArgMatches;
use std::error::Error;
pub fn handle_vm(matches: &ArgMatches) {
match matches.subcommand() {
Some(("deploy", args)) => cli_print(handle_vm_deploy(args)),
Some(("ssh", args)) => cli_print(handle_vm_ssh(args)),
Some(("list", args)) => cli_print(handle_vm_list(args)),
Some(("inspect", inspect_args)) => {
let uuid: String = inspect_args.get_one::<String>("uuid").unwrap().clone();
if *inspect_args.get_one::<bool>("show-node").unwrap() {
cli_print(snp::get_node_by_contract(&uuid).map_err(Into::into));
} else {
cli_print(snp::get_one_contract(&uuid).map_err(Into::into));
}
}
Some(("update", args)) => cli_print(handle_vm_update(args)),
Some(("delete", args)) => cli_print(handle_vm_delete(args)),
Some(("dtrfs", subcom_args)) => cli_print(handle_vm_dtrfs(subcom_args)),
Some(("distro", _)) => cli_print(Ok(crate::snp::Distro::get_template_list())),
_ => println!("No valid VM subcommand provided."),
}
}
fn handle_vm_deploy(matches: &ArgMatches) -> Result<snp::VmSshArgs, Box<dyn Error>> {
if let Some(path) = matches.get_one::<String>("yaml-path") {
return Ok(snp::deploy::Request::load_from_yaml(path)?);
}
let hostname = match matches.get_one::<String>("hostname") {
Some(hostname) => hostname.to_string(),
None => name_generator::random_vm_name(),
};
let location = matches.get_one::<String>("location").unwrap().as_str();
let ipv4: crate::snp::deploy::IPv4Config = match matches.get_one::<bool>("public-ip").unwrap() {
true => crate::snp::deploy::IPv4Config::PublicIPv4,
false => crate::snp::deploy::IPv4Config::PublishPorts(Vec::new()),
};
let distro =
crate::snp::Distro::from_string(matches.get_one::<String>("distribution").unwrap());
let vm_config = snp::deploy::Request {
hostname,
location: location.into(),
ipv4,
public_ipv6: false,
vcpus: *matches.get_one::<u32>("vcpus").unwrap(),
memory_mb: *matches.get_one::<u32>("memory").unwrap(),
disk_size_gb: *matches.get_one::<u32>("disk").unwrap(),
dtrfs: None,
hours: *matches.get_one::<u32>("hours").unwrap(),
price: *matches.get_one::<u64>("price").unwrap(),
distro: Some(distro),
};
Ok(vm_config.deploy()?)
}
fn handle_vm_ssh(ssh_args: &ArgMatches) -> Result<snp::VmSshArgs, Box<dyn Error>> {
let uuid: String = ssh_args.get_one::<String>("uuid").unwrap().clone();
Ok(snp::ssh(&uuid, *ssh_args.get_one::<bool>("just-print").unwrap())?)
}
fn handle_vm_list(update_vm_args: &ArgMatches) -> Result<Vec<snp::VmContract>, Box<dyn Error>> {
Ok(snp::list_contracts(*update_vm_args.get_one::<bool>("as-operator").unwrap())?)
}
fn handle_vm_update(update_vm_args: &ArgMatches) -> Result<SimpleOutput, Box<dyn Error>> {
let uuid = update_vm_args.get_one::<String>("uuid").unwrap().clone();
let memory = *update_vm_args.get_one::<u32>("memory").unwrap();
if memory > 0 && memory < 800 {
log::error!("At least 800MB of memory must be assgined to the VM");
return Ok(SimpleOutput::from(""));
}
snp::update::Request::process_request(
&uuid,
*update_vm_args.get_one::<u32>("vcpus").unwrap(),
memory,
*update_vm_args.get_one::<u32>("disk").unwrap(),
&update_vm_args.get_one::<String>("dtrfs").unwrap().to_string(),
)?;
let hours = *update_vm_args.get_one::<u32>("hours").unwrap();
if hours != 0 {
snp::update::expand_vm_hours(&uuid, hours)?;
}
Ok(SimpleOutput::from("VM successfully updated."))
}
fn handle_vm_delete(delete_args: &ArgMatches) -> Result<SimpleOutput, Box<dyn Error>> {
let uuid: String = delete_args.get_one::<String>("uuid").unwrap().clone();
snp::delete_contract(&uuid)?;
Ok(SimpleOutput::from("VM successfully deleted."))
}
fn handle_vm_dtrfs(_matches: &ArgMatches) -> Result<Vec<snp::Dtrfs>, Box<dyn Error>> {
Ok(crate::snp::Dtrfs::print_dtrfs_list())
}

@ -1,3 +1,4 @@
pub mod cli_handler;
pub mod deploy; pub mod deploy;
pub mod grpc; pub mod grpc;
mod injector; mod injector;