128 lines
4.4 KiB
Rust
128 lines
4.4 KiB
Rust
use crate::{
|
|
config::Config,
|
|
name_generator::random_app_name,
|
|
sgx::{
|
|
append_uuid_list,
|
|
grpc_brain::{get_one_app_node, new_app},
|
|
grpc_dtpm::{dtpm_client, set_config_pb, upload_files_pb},
|
|
package_entry_from_name,
|
|
utils::{calculate_nanolp_for_app, fetch_config, hratls_url_and_mr_enclave_from_app_id},
|
|
AppDeployResponse, Error, PackageElement,
|
|
},
|
|
snp,
|
|
};
|
|
use detee_shared::{
|
|
app_proto::{AppNodeFilters, AppNodeListResp, AppResource, NewAppReq},
|
|
sgx::pb::dtpm_proto::DtpmSetConfigReq,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_default_utils::*;
|
|
use tokio_retry::{strategy::FixedInterval, Retry};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
pub struct Reqwest {
|
|
#[serde(default = "random_app_name")]
|
|
pub app_name: String,
|
|
pub package_name: String,
|
|
pub vcpus: u32,
|
|
pub memory_mib: u32,
|
|
pub disk_size_mib: u32,
|
|
pub port: Vec<u32>,
|
|
#[serde(default = "default_u64::<1>")]
|
|
pub hours: u64,
|
|
#[serde(default)]
|
|
pub price: u64,
|
|
#[serde(default)]
|
|
pub location: String,
|
|
|
|
pub envs: Vec<String>,
|
|
pub args: Vec<String>,
|
|
}
|
|
|
|
impl Reqwest {
|
|
pub async fn deploy(self) -> Result<AppDeployResponse, Error> {
|
|
let node = self.get_app_node().await?;
|
|
let app_name = self.app_name.clone();
|
|
|
|
let locked_nano = calculate_nanolp_for_app(
|
|
self.vcpus,
|
|
self.memory_mib,
|
|
self.disk_size_mib,
|
|
self.hours,
|
|
self.price,
|
|
);
|
|
|
|
let PackageElement { package_url, mr_enclave, launch_config_url, .. } =
|
|
package_entry_from_name(&self.package_name).expect("Unknown package name");
|
|
|
|
let resource = Some(AppResource {
|
|
vcpus: self.vcpus,
|
|
memory_mib: self.memory_mib,
|
|
disk_size_mib: self.disk_size_mib,
|
|
ports: self.port.clone(),
|
|
});
|
|
|
|
let req = NewAppReq {
|
|
package_url: package_url,
|
|
node_pubkey: node.node_pubkey,
|
|
resource,
|
|
uuid: "".to_string(),
|
|
admin_pubkey: Config::get_detee_wallet()?,
|
|
price_per_unit: self.price,
|
|
locked_nano,
|
|
hratls_pubkey: Config::get_hratls_pubkey_hex()?,
|
|
public_package_mr_enclave: Some(mr_enclave.to_vec()),
|
|
app_name: self.app_name,
|
|
};
|
|
|
|
let new_app_res = new_app(req).await?;
|
|
|
|
let (hratls_uri, mr_enclave) =
|
|
hratls_url_and_mr_enclave_from_app_id(&new_app_res.uuid).await?;
|
|
|
|
let mr_enclave = mr_enclave.expect("App contract does not have a mr_enclave");
|
|
|
|
log::info!("hratls uri: {hratls_uri} mr_enclave: {mr_enclave:?}");
|
|
|
|
if new_app_res.error.is_empty() {
|
|
let launch_config = fetch_config(&launch_config_url).await?;
|
|
eprint!("Deploying...");
|
|
tokio::time::sleep(tokio::time::Duration::from_millis(2500)).await;
|
|
let dtpm_client = Retry::spawn(FixedInterval::from_millis(1000).take(30), || {
|
|
log::debug!("retrying attestation and launch config update");
|
|
eprint!(".");
|
|
dtpm_client(&hratls_uri, &mr_enclave)
|
|
})
|
|
.await?;
|
|
println!("");
|
|
upload_files_pb(launch_config.filesystems.clone(), &dtpm_client).await?;
|
|
|
|
let config_data = Some(launch_config.into());
|
|
log::trace!("Decoded the configuration... {:?}", config_data);
|
|
let req = DtpmSetConfigReq { config_data, ..Default::default() };
|
|
set_config_pb(req, &dtpm_client).await?;
|
|
|
|
append_uuid_list(&new_app_res.uuid, &app_name)?;
|
|
Ok((new_app_res, app_name).into())
|
|
} else {
|
|
Err(Error::Deployment(new_app_res.error))
|
|
}
|
|
}
|
|
|
|
pub async fn get_app_node(&self) -> Result<AppNodeListResp, Error> {
|
|
let location = snp::Location::from(self.location.as_str());
|
|
let app_node_filter = AppNodeFilters {
|
|
vcpus: self.vcpus,
|
|
memory_mib: self.memory_mib,
|
|
storage_mib: self.disk_size_mib,
|
|
country: location.country.clone().unwrap_or_default(),
|
|
region: location.region.clone().unwrap_or_default(),
|
|
city: location.city.clone().unwrap_or_default(),
|
|
ip: location.node_ip.clone().unwrap_or_default(),
|
|
node_pubkey: String::new(),
|
|
free_ports: (self.port.len() + 1) as u32,
|
|
};
|
|
Ok(get_one_app_node(app_node_filter).await?)
|
|
}
|
|
}
|