modified code based on new snp proto
This commit is contained in:
parent
d8488476c5
commit
abf09e8d26
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -348,6 +348,7 @@ dependencies = [
|
||||
"rand_core",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"sha2",
|
||||
"tokio",
|
||||
@ -1522,9 +1523,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.134"
|
||||
version = "1.0.135"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
|
||||
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
|
@ -20,6 +20,7 @@ rand = "0.8.5"
|
||||
tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] }
|
||||
tokio-stream = "0.1.17"
|
||||
tonic = "0.12"
|
||||
serde_json = "1.0.135"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.12"
|
||||
|
2
build.rs
2
build.rs
@ -1,6 +1,6 @@
|
||||
fn main() {
|
||||
tonic_build::configure()
|
||||
.build_server(true)
|
||||
.compile_protos(&["brain.proto"], &["proto"])
|
||||
.compile_protos(&["snp.proto"], &["proto"])
|
||||
.unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
|
||||
}
|
||||
|
@ -1,81 +1,14 @@
|
||||
syntax = "proto3";
|
||||
package brain;
|
||||
package snp_proto;
|
||||
|
||||
message Empty {
|
||||
}
|
||||
|
||||
message NodePubkey {
|
||||
string node_pubkey = 1;
|
||||
message Pubkey {
|
||||
string pubkey = 1;
|
||||
}
|
||||
|
||||
message RegisterNodeReq {
|
||||
string node_pubkey = 1;
|
||||
string owner_pubkey = 2;
|
||||
}
|
||||
|
||||
message NodeResourceReq {
|
||||
string node_pubkey = 1;
|
||||
uint32 avail_ports = 2;
|
||||
uint32 avail_ipv4 = 3;
|
||||
uint32 avail_ipv6 = 4;
|
||||
uint32 avail_vcpus = 5;
|
||||
uint32 avail_memory_mb = 6;
|
||||
uint32 avail_storage_gb = 7;
|
||||
uint32 max_ports_per_vm = 8;
|
||||
}
|
||||
|
||||
message MeasurementArgs {
|
||||
// this will be IP:Port of the dtrfs API
|
||||
// actually not a measurement arg, but needed for the injector
|
||||
string dtrfs_api_endpoint = 1;
|
||||
repeated uint32 exposed_ports = 2;
|
||||
string ovmf_hash = 5;
|
||||
// This is needed to allow the CLI to build the kernel params from known data.
|
||||
// The CLI will use the kernel params to get the measurement.
|
||||
repeated NewVmRespIP ips = 6;
|
||||
}
|
||||
|
||||
message NewVMReq {
|
||||
string uuid = 1; // UUID is empty when CLI sends request; brain sets UUID
|
||||
string hostname = 2;
|
||||
string admin_pubkey = 3;
|
||||
string node_pubkey = 4;
|
||||
repeated uint32 extra_ports = 5;
|
||||
bool public_ipv4 = 6;
|
||||
bool public_ipv6 = 7;
|
||||
uint32 disk_size_gb = 8;
|
||||
uint32 vcpus = 9;
|
||||
uint32 memory_mb = 10;
|
||||
string kernel_url = 11;
|
||||
string kernel_sha = 12;
|
||||
string dtrfs_url = 13;
|
||||
string dtrfs_sha = 14;
|
||||
}
|
||||
|
||||
message NewVMResp {
|
||||
string uuid = 1;
|
||||
string error = 2;
|
||||
MeasurementArgs args = 3;
|
||||
}
|
||||
|
||||
message UpdateVMReq {
|
||||
string uuid = 1;
|
||||
uint32 disk_size_gb = 2;
|
||||
uint32 vcpus = 3;
|
||||
uint32 memory_mb = 4;
|
||||
string kernel_url = 5;
|
||||
string kernel_sha = 6;
|
||||
string dtrfs_url = 7;
|
||||
string dtrfs_sha = 8;
|
||||
}
|
||||
|
||||
message UpdateVMResp {
|
||||
string uuid = 1;
|
||||
string error = 2;
|
||||
MeasurementArgs args = 3;
|
||||
}
|
||||
|
||||
message VMContract {
|
||||
message Contract {
|
||||
string uuid = 1;
|
||||
string hostname = 2;
|
||||
string admin_pubkey = 3;
|
||||
@ -92,33 +25,115 @@ message VMContract {
|
||||
string updated_at = 14;
|
||||
}
|
||||
|
||||
message ListVMContractsReq {
|
||||
string admin_pubkey = 1;
|
||||
string node_pubkey = 2;
|
||||
string uuid = 3;
|
||||
message MeasurementArgs {
|
||||
// this will be IP:Port of the dtrfs API
|
||||
// actually not a measurement arg, but needed for the injector
|
||||
string dtrfs_api_endpoint = 1;
|
||||
repeated uint32 exposed_ports = 2;
|
||||
string ovmf_hash = 5;
|
||||
// This is needed to allow the CLI to build the kernel params from known data.
|
||||
// The CLI will use the kernel params to get the measurement.
|
||||
repeated MeasurementIP ips = 6;
|
||||
}
|
||||
|
||||
message NewVmRespIP {
|
||||
message MeasurementIP {
|
||||
uint32 nic_index = 1;
|
||||
string address = 2;
|
||||
string mask = 3;
|
||||
string gateway = 4;
|
||||
}
|
||||
|
||||
message DeleteVMReq {
|
||||
message RegisterNodeReq {
|
||||
string node_pubkey = 1;
|
||||
string owner_pubkey = 2;
|
||||
string main_ip = 3;
|
||||
string country = 7;
|
||||
string region = 8;
|
||||
string city = 9;
|
||||
}
|
||||
|
||||
message NodeResources {
|
||||
string node_pubkey = 1;
|
||||
uint32 avail_ports = 2;
|
||||
uint32 avail_ipv4 = 3;
|
||||
uint32 avail_ipv6 = 4;
|
||||
uint32 avail_vcpus = 5;
|
||||
uint32 avail_memory_mb = 6;
|
||||
uint32 avail_storage_gb = 7;
|
||||
uint32 max_ports_per_vm = 8;
|
||||
}
|
||||
|
||||
message NewVmReq {
|
||||
string uuid = 1;
|
||||
string hostname = 2;
|
||||
string admin_pubkey = 3;
|
||||
string node_pubkey = 4;
|
||||
repeated uint32 extra_ports = 5;
|
||||
bool public_ipv4 = 6;
|
||||
bool public_ipv6 = 7;
|
||||
uint32 disk_size_gb = 8;
|
||||
uint32 vcpus = 9;
|
||||
uint32 memory_mb = 10;
|
||||
string kernel_url = 11;
|
||||
string kernel_sha = 12;
|
||||
string dtrfs_url = 13;
|
||||
string dtrfs_sha = 14;
|
||||
}
|
||||
|
||||
message NewVmResp {
|
||||
string uuid = 1;
|
||||
string error = 2;
|
||||
MeasurementArgs args = 3;
|
||||
}
|
||||
|
||||
message UpdateVmReq {
|
||||
string uuid = 1;
|
||||
uint32 disk_size_gb = 2;
|
||||
uint32 vcpus = 3;
|
||||
uint32 memory_mb = 4;
|
||||
string kernel_url = 5;
|
||||
string kernel_sha = 6;
|
||||
string dtrfs_url = 7;
|
||||
string dtrfs_sha = 8;
|
||||
}
|
||||
|
||||
message UpdateVmResp {
|
||||
string uuid = 1;
|
||||
string error = 2;
|
||||
MeasurementArgs args = 3;
|
||||
}
|
||||
|
||||
message DeleteVmReq {
|
||||
string uuid = 1;
|
||||
}
|
||||
|
||||
service BrainDaemonService {
|
||||
rpc RegisterNode (RegisterNodeReq) returns (Empty);
|
||||
rpc SendNodeResources (stream NodeResourceReq) returns (Empty);
|
||||
rpc GetNewVMReqs (NodePubkey) returns (stream NewVMReq);
|
||||
rpc SendNewVMResp (stream NewVMResp) returns (Empty);
|
||||
rpc GetDeleteVMReq (NodePubkey) returns (stream DeleteVMReq);
|
||||
rpc ListVMContracts (ListVMContractsReq) returns (stream VMContract);
|
||||
rpc GetUpdateVMReq (NodePubkey) returns (stream UpdateVMReq);
|
||||
rpc SendUpdateVMResp (stream UpdateVMResp) returns (Empty);
|
||||
//rpc GetMeasurementArgs (ListVMContractsReq) returns (stream MeasurementArgs);
|
||||
message BrainMessage {
|
||||
oneof Msg {
|
||||
NewVmReq new_vm_req = 1;
|
||||
UpdateVmReq update_vm_req = 2;
|
||||
DeleteVmReq delete_vm = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message DaemonMessage {
|
||||
oneof Msg {
|
||||
Pubkey pubkey = 1;
|
||||
NewVmResp new_vm_resp = 2;
|
||||
UpdateVmResp update_vm_resp = 3;
|
||||
NodeResources node_resources = 4;
|
||||
}
|
||||
}
|
||||
|
||||
service BrainDaemon {
|
||||
rpc RegisterNode (RegisterNodeReq) returns (stream Contract);
|
||||
rpc BrainMessages (Pubkey) returns (stream BrainMessage);
|
||||
rpc DaemonMessages (stream DaemonMessage) returns (Empty);
|
||||
}
|
||||
|
||||
message ListContractsReq {
|
||||
string admin_pubkey = 1;
|
||||
string node_pubkey = 2;
|
||||
string uuid = 3;
|
||||
}
|
||||
|
||||
message NodeFilters {
|
||||
@ -144,12 +159,11 @@ message NodeListResp {
|
||||
uint32 provider_rating = 7;
|
||||
}
|
||||
|
||||
service BrainCliService {
|
||||
rpc CreateVMContract (NewVMReq) returns (NewVMResp);
|
||||
rpc ListVMContracts (ListVMContractsReq) returns (stream VMContract);
|
||||
service BrainCli {
|
||||
rpc NewVm (NewVmReq) returns (NewVmResp);
|
||||
rpc ListContracts (ListContractsReq) returns (stream Contract);
|
||||
rpc ListNodes (NodeFilters) returns (stream NodeListResp);
|
||||
rpc GetOneNode (NodeFilters) returns (NodeListResp);
|
||||
rpc DeleteVM (DeleteVMReq) returns (Empty);
|
||||
rpc UpdateVM (UpdateVMReq) returns (UpdateVMResp);
|
||||
//rpc GetMeasurementArgs (ListVMContractsReq) returns (MeasurementArgs);
|
||||
rpc DeleteVm (DeleteVmReq) returns (Empty);
|
||||
rpc UpdateVm (UpdateVmReq) returns (UpdateVmResp);
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
#![allow(dead_code)]
|
||||
use anyhow::Result;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
@ -57,17 +56,9 @@ pub struct Config {
|
||||
}
|
||||
|
||||
mod range_format {
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use std::ops::Range;
|
||||
|
||||
pub fn serialize<S>(range: &Range<u16>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let range_repr = RangeRepr { start: range.start, end: range.end };
|
||||
range_repr.serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Range<u16>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
|
@ -1,16 +0,0 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub(crate) const DEFAULT_OVMF: &str = "/usr/share/edk2/ovmf/OVMF.amdsev.fd";
|
||||
pub(crate) const VM_BOOT_DIR: &str = "/var/lib/detee/boot/";
|
||||
pub(crate) const USED_RESOURCES: &str = "/etc/detee/daemon/used_resources.yaml";
|
||||
pub(crate) const VM_CONFIG_DIR: &str = "/etc/detee/daemon/vms/";
|
||||
pub(crate) const SECRET_KEY_PATH: &str = "/etc/detee/daemon/node_secret_key.pem";
|
||||
pub(crate) const DAEMON_CONFIG_PATH: &str = "/etc/detee/daemon/config.yaml";
|
||||
pub(crate) const START_VM_SCRIPT: &str = "/usr/local/bin/detee/start_qemu_vm.sh";
|
||||
// TODO: research if other CPU types provide better performance
|
||||
pub(crate) const QEMU_VM_CPU_TYPE: &str = "EPYC-v4";
|
||||
// If you modify this, also modify scripts/start_qemu_vm.sh
|
||||
pub(crate) const OVMF_HASH: &str =
|
||||
"0346619257269b9a61ee003e197d521b8e2283483070d163a34940d6a1d40d76";
|
||||
pub(crate) const OVMF_URL: &str =
|
||||
"https://drive.google.com/uc?export=download&id=1V-vLkaiLaGmFSjrN84Z6nELQOxKNAoSJ";
|
75
src/global.rs
Normal file
75
src/global.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use anyhow::Result;
|
||||
use lazy_static::lazy_static;
|
||||
use log::{info, warn};
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
pub(crate) const VM_BOOT_DIR: &str = "/var/lib/detee/boot/";
|
||||
pub(crate) const USED_RESOURCES: &str = "/etc/detee/daemon/used_resources.yaml";
|
||||
pub(crate) const VM_CONFIG_DIR: &str = "/etc/detee/daemon/vms/";
|
||||
pub(crate) const SECRET_KEY_PATH: &str = "/etc/detee/daemon/node_secret_key.pem";
|
||||
pub(crate) const DAEMON_CONFIG_PATH: &str = "/etc/detee/daemon/config.yaml";
|
||||
pub(crate) const START_VM_SCRIPT: &str = "/usr/local/bin/detee/start_qemu_vm.sh";
|
||||
// TODO: research if other CPU types provide better performance
|
||||
pub(crate) const QEMU_VM_CPU_TYPE: &str = "EPYC-v4";
|
||||
// If you modify this, also modify scripts/start_qemu_vm.sh
|
||||
pub(crate) const OVMF_HASH: &str =
|
||||
"0346619257269b9a61ee003e197d521b8e2283483070d163a34940d6a1d40d76";
|
||||
pub(crate) const OVMF_URL: &str =
|
||||
"https://drive.google.com/uc?export=download&id=1V-vLkaiLaGmFSjrN84Z6nELQOxKNAoSJ";
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PUBLIC_KEY: String = get_public_key();
|
||||
pub static ref IP_INFO: IPInfo = get_ip_info().unwrap();
|
||||
}
|
||||
|
||||
fn create_secret_key() -> Result<ed25519_dalek::SigningKey> {
|
||||
use ed25519_dalek::pkcs8::{spki::der::pem::LineEnding, EncodePrivateKey};
|
||||
let key_path = SECRET_KEY_PATH;
|
||||
info!("Creating new secret key at {}", key_path);
|
||||
let sk = ed25519_dalek::SigningKey::generate(&mut rand_core::OsRng);
|
||||
let sk_pem = sk.to_pkcs8_pem(LineEnding::default()).unwrap();
|
||||
let mut file = File::create(key_path)?;
|
||||
file.write_all(sk_pem.as_bytes())?;
|
||||
Ok(sk)
|
||||
}
|
||||
|
||||
fn load_secret_key() -> Result<ed25519_dalek::SigningKey> {
|
||||
use ed25519_dalek::pkcs8::DecodePrivateKey;
|
||||
let secret_key_pem = match std::fs::read_to_string(SECRET_KEY_PATH) {
|
||||
Ok(secret_key_pem) => secret_key_pem,
|
||||
Err(e) => {
|
||||
warn!("Could not load secret key due to error: {e:?}");
|
||||
return Ok(create_secret_key()?);
|
||||
}
|
||||
};
|
||||
Ok(ed25519_dalek::SigningKey::from_pkcs8_pem(&secret_key_pem)?)
|
||||
}
|
||||
|
||||
pub fn get_public_key() -> String {
|
||||
use ed25519_dalek::pkcs8::{spki::der::pem::LineEnding, EncodePublicKey};
|
||||
let pubkey = load_secret_key()
|
||||
.unwrap()
|
||||
.verifying_key()
|
||||
.to_public_key_pem(LineEnding::default())
|
||||
.unwrap()
|
||||
.lines()
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
log::info!("Loaded the following public key: {pubkey}");
|
||||
pubkey
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Clone)]
|
||||
pub struct IPInfo {
|
||||
pub country: String,
|
||||
pub region: String,
|
||||
pub city: String,
|
||||
pub ip: String,
|
||||
}
|
||||
|
||||
fn get_ip_info() -> anyhow::Result<IPInfo> {
|
||||
let body = reqwest::blocking::get("https://ipinfo.io/".to_string())?.text()?;
|
||||
info!("Got the following data from ipinfo.io: {body}");
|
||||
Ok(serde_json::de::from_str(&body)?)
|
||||
}
|
228
src/grpc.rs
228
src/grpc.rs
@ -1,76 +1,53 @@
|
||||
#![allow(dead_code)]
|
||||
pub mod brain {
|
||||
tonic::include_proto!("brain");
|
||||
}
|
||||
|
||||
use crate::snp_proto::DaemonMessage;
|
||||
use anyhow::Result;
|
||||
use brain::{
|
||||
brain_daemon_service_client::BrainDaemonServiceClient, DeleteVmReq, ListVmContractsReq,
|
||||
NewVmReq, NewVmResp, NodePubkey, NodeResourceReq, RegisterNodeReq, UpdateVmReq, UpdateVmResp,
|
||||
VmContract,
|
||||
use log::{debug, info, warn};
|
||||
use snp_proto::{
|
||||
brain_daemon_client::BrainDaemonClient, BrainMessage, Contract, Pubkey, RegisterNodeReq,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use log::{debug, error, info, warn};
|
||||
use std::{fs::File, io::Write};
|
||||
use tokio::{
|
||||
sync::mpsc::{Receiver, Sender},
|
||||
task::JoinSet,
|
||||
};
|
||||
use tokio_stream::{wrappers::ReceiverStream, StreamExt};
|
||||
use tonic::transport::Channel;
|
||||
use crate::global::*;
|
||||
|
||||
lazy_static! {
|
||||
static ref PUBLIC_KEY: String = get_public_key();
|
||||
pub mod snp_proto {
|
||||
tonic::include_proto!("snp_proto");
|
||||
}
|
||||
|
||||
fn create_secret_key() -> Result<ed25519_dalek::SigningKey> {
|
||||
use ed25519_dalek::pkcs8::{spki::der::pem::LineEnding, EncodePrivateKey};
|
||||
let key_path = crate::constants::SECRET_KEY_PATH;
|
||||
info!("Creating new secret key at {}", key_path);
|
||||
let sk = ed25519_dalek::SigningKey::generate(&mut rand_core::OsRng);
|
||||
let sk_pem = sk.to_pkcs8_pem(LineEnding::default()).unwrap();
|
||||
let mut file = File::create(key_path)?;
|
||||
file.write_all(sk_pem.as_bytes())?;
|
||||
Ok(sk)
|
||||
impl From<snp_proto::NewVmResp> for snp_proto::DaemonMessage {
|
||||
fn from(value: snp_proto::NewVmResp) -> Self {
|
||||
snp_proto::DaemonMessage { msg: Some(snp_proto::daemon_message::Msg::NewVmResp(value)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn load_secret_key() -> Result<ed25519_dalek::SigningKey> {
|
||||
use ed25519_dalek::pkcs8::DecodePrivateKey;
|
||||
let secret_key_pem = match std::fs::read_to_string(crate::constants::SECRET_KEY_PATH) {
|
||||
Ok(secret_key_pem) => secret_key_pem,
|
||||
Err(e) => {
|
||||
warn!("Could not load secret key due to error: {e:?}");
|
||||
return Ok(create_secret_key()?);
|
||||
}
|
||||
impl From<snp_proto::UpdateVmResp> for snp_proto::DaemonMessage {
|
||||
fn from(value: snp_proto::UpdateVmResp) -> Self {
|
||||
snp_proto::DaemonMessage { msg: Some(snp_proto::daemon_message::Msg::UpdateVmResp(value)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<snp_proto::NodeResources> for snp_proto::DaemonMessage {
|
||||
fn from(value: snp_proto::NodeResources) -> Self {
|
||||
snp_proto::DaemonMessage { msg: Some(snp_proto::daemon_message::Msg::NodeResources(value)) }
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn register_node(brain_url: String) -> Result<Vec<Contract>> {
|
||||
let mut client = BrainDaemonClient::connect(brain_url).await?;
|
||||
debug!("Starting node registration...");
|
||||
let ip_info = IP_INFO.clone();
|
||||
let req = RegisterNodeReq {
|
||||
node_pubkey: PUBLIC_KEY.clone(),
|
||||
owner_pubkey: "IamTheOwnerOf".to_string() + &PUBLIC_KEY,
|
||||
main_ip: ip_info.ip,
|
||||
country: ip_info.country,
|
||||
region: ip_info.region,
|
||||
city: ip_info.city,
|
||||
};
|
||||
Ok(ed25519_dalek::SigningKey::from_pkcs8_pem(&secret_key_pem)?)
|
||||
}
|
||||
|
||||
pub fn get_public_key() -> String {
|
||||
use ed25519_dalek::pkcs8::{spki::der::pem::LineEnding, EncodePublicKey};
|
||||
let pubkey = load_secret_key()
|
||||
.unwrap()
|
||||
.verifying_key()
|
||||
.to_public_key_pem(LineEnding::default())
|
||||
.unwrap()
|
||||
.lines()
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
log::info!("Loaded the following public key: {pubkey}");
|
||||
pubkey
|
||||
}
|
||||
|
||||
pub async fn list_contracts(brain_url: String) -> Result<Vec<VmContract>> {
|
||||
let mut client = BrainDaemonServiceClient::connect(brain_url).await?;
|
||||
let mut contracts = Vec::new();
|
||||
let mut grpc_stream = client
|
||||
.list_vm_contracts(ListVmContractsReq {
|
||||
node_pubkey: PUBLIC_KEY.to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
let mut grpc_stream = client.register_node(req).await?.into_inner();
|
||||
while let Some(stream_update) = grpc_stream.next().await {
|
||||
match stream_update {
|
||||
Ok(node) => {
|
||||
@ -86,18 +63,18 @@ pub async fn list_contracts(brain_url: String) -> Result<Vec<VmContract>> {
|
||||
Ok(contracts)
|
||||
}
|
||||
|
||||
async fn listen_for_new_vm_reqs(
|
||||
mut client: BrainDaemonServiceClient<Channel>,
|
||||
tx: Sender<NewVmReq>,
|
||||
async fn receive_messages(
|
||||
mut client: BrainDaemonClient<Channel>,
|
||||
tx: Sender<BrainMessage>,
|
||||
) -> Result<()> {
|
||||
debug!("starting listen_for_new_vm_reqs");
|
||||
let node_pubkey = PUBLIC_KEY.clone();
|
||||
let mut grpc_stream = client.get_new_vm_reqs(NodePubkey { node_pubkey }).await?.into_inner();
|
||||
debug!("starting to listen for messages from brain");
|
||||
let pubkey = PUBLIC_KEY.clone();
|
||||
let mut grpc_stream = client.brain_messages(Pubkey { pubkey }).await?.into_inner();
|
||||
while let Some(stream_update) = grpc_stream.next().await {
|
||||
match stream_update {
|
||||
Ok(req) => {
|
||||
info!("Received new vm request: {req:?}");
|
||||
let _ = tx.send(req).await;
|
||||
Ok(msg) => {
|
||||
info!("Received message from brain: {msg:?}");
|
||||
let _ = tx.send(msg).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Brain disconnected from listen_for_new_vm_reqs: {e}");
|
||||
@ -108,121 +85,34 @@ async fn listen_for_new_vm_reqs(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_newvm_resp(
|
||||
mut client: BrainDaemonServiceClient<Channel>,
|
||||
rx: Receiver<NewVmResp>,
|
||||
async fn send_messages(
|
||||
mut client: BrainDaemonClient<Channel>,
|
||||
rx: Receiver<DaemonMessage>,
|
||||
tx: Sender<DaemonMessage>,
|
||||
) -> Result<()> {
|
||||
debug!("starting send_newvm_resp stream");
|
||||
debug!("starting daemon message stream to brain");
|
||||
let pubkey = PUBLIC_KEY.clone();
|
||||
let rx_stream = ReceiverStream::new(rx);
|
||||
client.send_new_vm_resp(rx_stream).await?;
|
||||
tx.send(DaemonMessage { msg: Some(snp_proto::daemon_message::Msg::Pubkey(Pubkey { pubkey })) })
|
||||
.await?;
|
||||
client.daemon_messages(rx_stream).await?;
|
||||
debug!("send_newvm_resp is about to exit");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_node_resources(
|
||||
mut client: BrainDaemonServiceClient<Channel>,
|
||||
rx: Receiver<NodeResourceReq>,
|
||||
) -> Result<()> {
|
||||
debug!("starting send_newvm_resp stream");
|
||||
let rx_stream = ReceiverStream::new(rx).map(|mut node_resources| {
|
||||
node_resources.node_pubkey = get_public_key();
|
||||
node_resources
|
||||
});
|
||||
client.send_node_resources(rx_stream).await?;
|
||||
debug!("send_newvm_resp is about to exit");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn register_node(mut client: BrainDaemonServiceClient<Channel>) {
|
||||
debug!("Starting node registration...");
|
||||
let req = RegisterNodeReq {
|
||||
node_pubkey: PUBLIC_KEY.clone(),
|
||||
owner_pubkey: "IamTheOwnerOf".to_string() + &PUBLIC_KEY,
|
||||
};
|
||||
match client.register_node(req).await {
|
||||
Ok(_) => {
|
||||
info!("Registered as 10.0.10.1 from Bruma/Cyrodiil with ID {}", PUBLIC_KEY.clone())
|
||||
}
|
||||
Err(e) => error!("Could not register node data: {e:?}"),
|
||||
};
|
||||
}
|
||||
|
||||
async fn listen_for_deleted_vms(
|
||||
mut client: BrainDaemonServiceClient<Channel>,
|
||||
tx: Sender<DeleteVmReq>,
|
||||
) -> Result<()> {
|
||||
debug!("starting listen_for_new_vm_reqs");
|
||||
let node_pubkey = PUBLIC_KEY.clone();
|
||||
let mut grpc_stream = client.get_delete_vm_req(NodePubkey { node_pubkey }).await?.into_inner();
|
||||
while let Some(stream_update) = grpc_stream.next().await {
|
||||
match stream_update {
|
||||
Ok(req) => {
|
||||
info!("Received delete vm request: {req:?}");
|
||||
let _ = tx.send(req).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Brain disconnected from listen_for_deleted_vms: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("listen_for_new_vm_reqs is about to exit");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn listen_for_update_vm_reqs(
|
||||
mut client: BrainDaemonServiceClient<Channel>,
|
||||
tx: Sender<UpdateVmReq>,
|
||||
) -> Result<()> {
|
||||
debug!("starting listen_for_update_vm_reqs");
|
||||
let node_pubkey = PUBLIC_KEY.clone();
|
||||
let mut grpc_stream = client.get_update_vm_req(NodePubkey { node_pubkey }).await?.into_inner();
|
||||
while let Some(stream_update) = grpc_stream.next().await {
|
||||
match stream_update {
|
||||
Ok(req) => {
|
||||
info!("Received update vm request: {req:?}");
|
||||
let _ = tx.send(req).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Brain disconnected from listen_for_update_vm_reqs: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("listen_for_update_vm_reqs is about to exit");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_updatevm_resp(
|
||||
mut client: BrainDaemonServiceClient<Channel>,
|
||||
rx: Receiver<UpdateVmResp>,
|
||||
) -> Result<()> {
|
||||
debug!("starting send_updatevm_resp stream");
|
||||
let rx_stream = ReceiverStream::new(rx);
|
||||
client.send_update_vm_resp(rx_stream).await?;
|
||||
debug!("send_updatevm_resp is about to exit");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct ConnectionData {
|
||||
pub brain_url: String,
|
||||
pub newvm_tx: Sender<NewVmReq>,
|
||||
pub confirm_vm_rx: Receiver<NewVmResp>,
|
||||
pub updatevm_tx: Sender<UpdateVmReq>,
|
||||
pub confirm_updatevm_rx: Receiver<UpdateVmResp>,
|
||||
pub delete_vm_tx: Sender<DeleteVmReq>,
|
||||
pub resources_rx: Receiver<NodeResourceReq>,
|
||||
pub brain_msg_tx: Sender<BrainMessage>,
|
||||
pub daemon_msg_rx: Receiver<DaemonMessage>,
|
||||
pub daemon_msg_tx: Sender<DaemonMessage>,
|
||||
}
|
||||
|
||||
pub async fn connect_and_run(cd: ConnectionData) -> Result<()> {
|
||||
let client = BrainDaemonServiceClient::connect(cd.brain_url).await?;
|
||||
let client = BrainDaemonClient::connect(cd.brain_url).await?;
|
||||
let mut streaming_tasks = JoinSet::new();
|
||||
|
||||
register_node(client.clone()).await;
|
||||
streaming_tasks.spawn(listen_for_new_vm_reqs(client.clone(), cd.newvm_tx));
|
||||
streaming_tasks.spawn(send_newvm_resp(client.clone(), cd.confirm_vm_rx));
|
||||
streaming_tasks.spawn(listen_for_update_vm_reqs(client.clone(), cd.updatevm_tx));
|
||||
streaming_tasks.spawn(send_updatevm_resp(client.clone(), cd.confirm_updatevm_rx));
|
||||
streaming_tasks.spawn(listen_for_deleted_vms(client.clone(), cd.delete_vm_tx));
|
||||
streaming_tasks.spawn(send_node_resources(client.clone(), cd.resources_rx));
|
||||
streaming_tasks.spawn(receive_messages(client.clone(), cd.brain_msg_tx));
|
||||
streaming_tasks.spawn(send_messages(client.clone(), cd.daemon_msg_rx, cd.daemon_msg_tx));
|
||||
|
||||
let task_output = streaming_tasks.join_next().await;
|
||||
warn!("One stream exited: {task_output:?}");
|
||||
|
156
src/main.rs
156
src/main.rs
@ -1,10 +1,10 @@
|
||||
#[allow(dead_code)]
|
||||
mod config;
|
||||
mod constants;
|
||||
mod global;
|
||||
mod grpc;
|
||||
mod state;
|
||||
|
||||
use crate::{config::Config, grpc::brain};
|
||||
use crate::global::*;
|
||||
use crate::{config::Config, grpc::snp_proto};
|
||||
use anyhow::Result;
|
||||
use log::{debug, info, warn};
|
||||
use tokio::{
|
||||
@ -14,12 +14,8 @@ use tokio::{
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct VMHandler {
|
||||
new_vm_req_chan: Receiver<brain::NewVmReq>,
|
||||
new_vm_resp_chan: Sender<brain::NewVmResp>,
|
||||
update_vm_req_chan: Receiver<brain::UpdateVmReq>,
|
||||
update_vm_resp_chan: Sender<brain::UpdateVmResp>,
|
||||
delete_vm_chan: Receiver<brain::DeleteVmReq>,
|
||||
resources_chan: Sender<brain::NodeResourceReq>,
|
||||
receiver: Receiver<snp_proto::BrainMessage>,
|
||||
sender: Sender<snp_proto::DaemonMessage>,
|
||||
config: Config,
|
||||
res: state::Resources,
|
||||
}
|
||||
@ -27,14 +23,10 @@ struct VMHandler {
|
||||
#[allow(dead_code)]
|
||||
impl VMHandler {
|
||||
fn new(
|
||||
new_vm_req_chan: Receiver<brain::NewVmReq>,
|
||||
new_vm_resp_chan: Sender<brain::NewVmResp>,
|
||||
update_vm_req_chan: Receiver<brain::UpdateVmReq>,
|
||||
update_vm_resp_chan: Sender<brain::UpdateVmResp>,
|
||||
delete_vm_chan: Receiver<brain::DeleteVmReq>,
|
||||
resources_chan: Sender<brain::NodeResourceReq>,
|
||||
receiver: Receiver<snp_proto::BrainMessage>,
|
||||
sender: Sender<snp_proto::DaemonMessage>,
|
||||
) -> Self {
|
||||
let config = match Config::load_from_disk(crate::constants::DAEMON_CONFIG_PATH) {
|
||||
let config = match Config::load_from_disk(DAEMON_CONFIG_PATH) {
|
||||
Ok(config) => config,
|
||||
Err(e) => panic!("Could not load config: {e:?}"),
|
||||
};
|
||||
@ -46,16 +38,7 @@ impl VMHandler {
|
||||
state::Resources::new(&config.volumes)
|
||||
}
|
||||
};
|
||||
Self {
|
||||
new_vm_req_chan,
|
||||
new_vm_resp_chan,
|
||||
update_vm_req_chan,
|
||||
update_vm_resp_chan,
|
||||
delete_vm_chan,
|
||||
resources_chan,
|
||||
config,
|
||||
res,
|
||||
}
|
||||
Self { receiver, sender, config, res }
|
||||
}
|
||||
|
||||
fn get_available_ips(&self) -> (u32, u32) {
|
||||
@ -85,8 +68,8 @@ impl VMHandler {
|
||||
}
|
||||
}
|
||||
let avail_storage_gb = avail_storage_gb as u32;
|
||||
let res = brain::NodeResourceReq {
|
||||
node_pubkey: String::new(),
|
||||
let res = snp_proto::NodeResources {
|
||||
node_pubkey: PUBLIC_KEY.clone(),
|
||||
avail_ports: (self.config.public_port_range.len() - self.res.reserved_ports.len())
|
||||
as u32,
|
||||
avail_ipv4,
|
||||
@ -97,29 +80,33 @@ impl VMHandler {
|
||||
max_ports_per_vm: self.config.max_ports_per_vm as u32,
|
||||
};
|
||||
debug!("sending node resources on brain: {res:?}");
|
||||
let _ = self.resources_chan.send(res).await;
|
||||
let _ = self.sender.send(res.into()).await;
|
||||
}
|
||||
|
||||
async fn handle_new_vm_req(&mut self, new_vm_req: brain::NewVmReq) {
|
||||
async fn handle_new_vm_req(&mut self, new_vm_req: snp_proto::NewVmReq) {
|
||||
debug!("Processing new vm request: {new_vm_req:?}");
|
||||
let uuid = new_vm_req.uuid.clone();
|
||||
match state::VM::new(new_vm_req.into(), &self.config, &mut self.res) {
|
||||
Ok(vm) => match vm.start() {
|
||||
Ok(_) => {
|
||||
info!("Succesfully started VM {uuid}");
|
||||
let _ = self.new_vm_resp_chan.send(vm.into()).await;
|
||||
let vm: snp_proto::NewVmResp = vm.into();
|
||||
let _ = self.sender.send(vm.into()).await;
|
||||
self.send_node_resources().await;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Could not start VM {uuid}: {e:?}");
|
||||
let _ = self
|
||||
.new_vm_resp_chan
|
||||
.send(brain::NewVmResp {
|
||||
uuid,
|
||||
error: "This node has an internal error. Choose another node."
|
||||
.to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.sender
|
||||
.send(
|
||||
snp_proto::NewVmResp {
|
||||
uuid,
|
||||
error: "This node has an internal error. Choose another node."
|
||||
.to_string(),
|
||||
..Default::default()
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
},
|
||||
@ -129,54 +116,62 @@ impl VMHandler {
|
||||
"Got NewVmReq for VM {}, that already exist. Will send NewVmResp.",
|
||||
vm.uuid
|
||||
);
|
||||
let _ = self.new_vm_resp_chan.send(vm.into()).await;
|
||||
let vm: snp_proto::NewVmResp = vm.into();
|
||||
let _ = self.sender.send(vm.into()).await;
|
||||
}
|
||||
_ => {
|
||||
warn!("Refusing to service vm {uuid} due to error: {e:?}");
|
||||
let _ = self
|
||||
.new_vm_resp_chan
|
||||
.send(brain::NewVmResp {
|
||||
uuid,
|
||||
error: format!("{e:?}"),
|
||||
..Default::default()
|
||||
})
|
||||
.sender
|
||||
.send(
|
||||
snp_proto::NewVmResp {
|
||||
uuid,
|
||||
error: format!("{e:?}"),
|
||||
..Default::default()
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_update_vm_req(&mut self, update_vm_req: brain::UpdateVmReq) -> Result<()> {
|
||||
async fn handle_update_vm_req(&mut self, update_vm_req: snp_proto::UpdateVmReq) -> Result<()> {
|
||||
debug!("Processing update vm request: {update_vm_req:?}");
|
||||
let vm_id = update_vm_req.uuid.clone();
|
||||
let content =
|
||||
std::fs::read_to_string(constants::VM_CONFIG_DIR.to_string() + &vm_id + ".yaml")?;
|
||||
std::fs::read_to_string(VM_CONFIG_DIR.to_string() + &vm_id + ".yaml")?;
|
||||
let mut vm: state::VM = serde_yaml::from_str(&content)?;
|
||||
match vm.update(update_vm_req.into(), &self.config, &mut self.res) {
|
||||
Ok(_) => {
|
||||
info!("Succesfully updated VM {vm_id}");
|
||||
let _ = self.update_vm_resp_chan.send(vm.into()).await;
|
||||
let vm: snp_proto::UpdateVmResp = vm.into();
|
||||
let _ = self.sender.send(vm.into()).await;
|
||||
self.send_node_resources().await;
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("Unable to update vm {vm_id} due to error: {e:?}");
|
||||
let _ = self
|
||||
.update_vm_resp_chan
|
||||
.send(brain::UpdateVmResp {
|
||||
uuid: vm_id,
|
||||
error: format!("{e:?}"),
|
||||
..Default::default()
|
||||
})
|
||||
.sender
|
||||
.send(
|
||||
snp_proto::UpdateVmResp {
|
||||
uuid: vm_id,
|
||||
error: format!("{e:?}"),
|
||||
..Default::default()
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_delete_vm(&mut self, delete_vm_req: brain::DeleteVmReq) -> Result<()> {
|
||||
fn handle_delete_vm(&mut self, delete_vm_req: snp_proto::DeleteVmReq) -> Result<()> {
|
||||
let vm_id = delete_vm_req.uuid;
|
||||
let content =
|
||||
std::fs::read_to_string(constants::VM_CONFIG_DIR.to_string() + &vm_id + ".yaml")?;
|
||||
std::fs::read_to_string(VM_CONFIG_DIR.to_string() + &vm_id + ".yaml")?;
|
||||
let vm: state::VM = serde_yaml::from_str(&content)?;
|
||||
vm.delete(&mut self.res)?;
|
||||
Ok(())
|
||||
@ -184,17 +179,17 @@ impl VMHandler {
|
||||
|
||||
async fn run(mut self) {
|
||||
self.send_node_resources().await;
|
||||
loop {
|
||||
tokio::select! {
|
||||
Some(new_vm_req) = self.new_vm_req_chan.recv() => {
|
||||
while let Some(brain_msg) = self.receiver.recv().await {
|
||||
match brain_msg.msg {
|
||||
Some(snp_proto::brain_message::Msg::NewVmReq(new_vm_req)) => {
|
||||
self.handle_new_vm_req(new_vm_req).await;
|
||||
}
|
||||
Some(update_vm_req) = self.update_vm_req_chan.recv() => {
|
||||
Some(snp_proto::brain_message::Msg::UpdateVmReq(update_vm_req)) => {
|
||||
if let Err(e) = self.handle_update_vm_req(update_vm_req).await {
|
||||
log::error!("Could not update vm: {e:?}");
|
||||
}
|
||||
}
|
||||
Some(delete_vm_req) = self.delete_vm_chan.recv() => {
|
||||
Some(snp_proto::brain_message::Msg::DeleteVm(delete_vm_req)) => {
|
||||
let uuid = delete_vm_req.uuid.clone();
|
||||
if let Err(e) = self.handle_delete_vm(delete_vm_req) {
|
||||
log::error!("Could not delete vm {uuid}: {e:?}");
|
||||
@ -202,20 +197,17 @@ impl VMHandler {
|
||||
self.send_node_resources().await;
|
||||
}
|
||||
}
|
||||
else => {
|
||||
log::error!("All data channels closed.");
|
||||
return;
|
||||
}
|
||||
None => debug!("Received None from the Brain."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_deleted_contracts(&mut self, contracts: Vec<brain::VmContract>) {
|
||||
fn clear_deleted_contracts(&mut self, contracts: Vec<snp_proto::Contract>) {
|
||||
for uuid in self.res.existing_vms.clone() {
|
||||
if contracts.iter().find(|c| c.uuid == uuid).is_none() {
|
||||
info!("VM {uuid} exists locally but not found in brain. Deleting...");
|
||||
let content = match std::fs::read_to_string(
|
||||
crate::constants::VM_CONFIG_DIR.to_string() + &uuid + ".yaml",
|
||||
VM_CONFIG_DIR.to_string() + &uuid + ".yaml",
|
||||
) {
|
||||
Ok(content) => content,
|
||||
Err(e) => {
|
||||
@ -244,25 +236,14 @@ async fn main() {
|
||||
env_logger::builder().filter_level(log::LevelFilter::Debug).init();
|
||||
|
||||
loop {
|
||||
let (newvm_tx, newvm_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (confirm_vm_tx, confirm_vm_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (updatevm_tx, updatevm_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (confirm_updatevm_tx, confirm_updatevm_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (delete_vm_tx, delete_vm_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (resources_tx, resources_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (brain_msg_tx, brain_msg_rx) = tokio::sync::mpsc::channel(6);
|
||||
let (daemon_msg_tx, daemon_msg_rx) = tokio::sync::mpsc::channel(6);
|
||||
|
||||
let mut vm_handler = VMHandler::new(
|
||||
newvm_rx,
|
||||
confirm_vm_tx,
|
||||
updatevm_rx,
|
||||
confirm_updatevm_tx,
|
||||
delete_vm_rx,
|
||||
resources_tx,
|
||||
);
|
||||
let mut vm_handler = VMHandler::new(brain_msg_rx, daemon_msg_tx.clone());
|
||||
let brain_url = vm_handler.config.brain_url.clone();
|
||||
|
||||
info!("Trying to get VM Contracts from Brain to see if some Contracts got removed...");
|
||||
match grpc::list_contracts(brain_url.clone()).await {
|
||||
info!("Registering with the brain and getting back VM Contracts (if they exist).");
|
||||
match grpc::register_node(brain_url.clone()).await {
|
||||
Ok(contracts) => vm_handler.clear_deleted_contracts(contracts),
|
||||
Err(e) => log::error!("Could not get contracts from brain: {e:?}"),
|
||||
};
|
||||
@ -274,12 +255,9 @@ async fn main() {
|
||||
info!("Connecting to brain...");
|
||||
if let Err(e) = grpc::connect_and_run(grpc::ConnectionData {
|
||||
brain_url,
|
||||
newvm_tx,
|
||||
confirm_vm_rx,
|
||||
updatevm_tx,
|
||||
confirm_updatevm_rx,
|
||||
delete_vm_tx,
|
||||
resources_rx,
|
||||
brain_msg_tx,
|
||||
daemon_msg_rx,
|
||||
daemon_msg_tx,
|
||||
})
|
||||
.await
|
||||
{
|
||||
|
43
src/state.rs
43
src/state.rs
@ -1,9 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
use crate::{
|
||||
config::Config,
|
||||
constants::*,
|
||||
grpc::brain,
|
||||
};
|
||||
use crate::{config::Config, global::*, grpc::snp_proto};
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::info;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -366,7 +362,7 @@ pub struct VM {
|
||||
}
|
||||
|
||||
impl VM {
|
||||
fn to_brain_vm_resp<T>(self, build_resp: impl FnOnce(brain::MeasurementArgs) -> T) -> T {
|
||||
fn to_grpc_response<T>(self, build_resp: impl FnOnce(snp_proto::MeasurementArgs) -> T) -> T {
|
||||
let mut nic_index: u32 = if self.fw_ports.is_empty() { 0 } else { 1 };
|
||||
let mut ips = Vec::new();
|
||||
let mut dtrfs_api_endpoint = String::new();
|
||||
@ -377,7 +373,7 @@ impl VM {
|
||||
if ip.address.parse::<std::net::Ipv4Addr>().is_ok() {
|
||||
dtrfs_api_endpoint = ip.address.clone();
|
||||
}
|
||||
ips.push(brain::NewVmRespIp {
|
||||
ips.push(snp_proto::MeasurementIp {
|
||||
nic_index,
|
||||
address: ip.address,
|
||||
mask: ip.mask,
|
||||
@ -390,24 +386,24 @@ impl VM {
|
||||
if !dtrfs_api_endpoint.is_empty() {
|
||||
dtrfs_api_endpoint += ":22";
|
||||
} else {
|
||||
dtrfs_api_endpoint += &format!(":{}", self.fw_ports[0].0);
|
||||
dtrfs_api_endpoint += &format!("{}:{}", IP_INFO.ip, self.fw_ports[0].0);
|
||||
}
|
||||
|
||||
let args = brain::MeasurementArgs {
|
||||
let args = snp_proto::MeasurementArgs {
|
||||
dtrfs_api_endpoint,
|
||||
exposed_ports: self.fw_ports.iter().map(|(host_port, _)| *host_port as u32).collect(),
|
||||
ips,
|
||||
ovmf_hash: crate::constants::OVMF_HASH.to_string(),
|
||||
ovmf_hash: OVMF_HASH.to_string(),
|
||||
};
|
||||
|
||||
build_resp(args)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<brain::NewVmResp> for VM {
|
||||
fn into(self) -> brain::NewVmResp {
|
||||
impl Into<snp_proto::NewVmResp> for VM {
|
||||
fn into(self) -> snp_proto::NewVmResp {
|
||||
let uuid = self.uuid.clone();
|
||||
self.to_brain_vm_resp(|args| brain::NewVmResp {
|
||||
self.to_grpc_response(|args| snp_proto::NewVmResp {
|
||||
uuid,
|
||||
args: Some(args),
|
||||
error: "".to_string(),
|
||||
@ -415,10 +411,10 @@ impl Into<brain::NewVmResp> for VM {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<brain::UpdateVmResp> for VM {
|
||||
fn into(self) -> brain::UpdateVmResp {
|
||||
impl Into<snp_proto::UpdateVmResp> for VM {
|
||||
fn into(self) -> snp_proto::UpdateVmResp {
|
||||
let uuid = self.uuid.clone();
|
||||
self.to_brain_vm_resp(|args| brain::UpdateVmResp {
|
||||
self.to_grpc_response(|args| snp_proto::UpdateVmResp {
|
||||
uuid,
|
||||
args: Some(args),
|
||||
error: "".to_string(),
|
||||
@ -443,8 +439,8 @@ pub struct NewVMRequest {
|
||||
dtrfs_sha: String,
|
||||
}
|
||||
|
||||
impl From<brain::NewVmReq> for NewVMRequest {
|
||||
fn from(req: brain::NewVmReq) -> Self {
|
||||
impl From<snp_proto::NewVmReq> for NewVMRequest {
|
||||
fn from(req: snp_proto::NewVmReq) -> Self {
|
||||
Self {
|
||||
uuid: req.uuid,
|
||||
hostname: req.hostname,
|
||||
@ -476,8 +472,8 @@ pub struct UpdateVMReq {
|
||||
dtrfs_sha: String,
|
||||
}
|
||||
|
||||
impl From<brain::UpdateVmReq> for UpdateVMReq {
|
||||
fn from(req: brain::UpdateVmReq) -> Self {
|
||||
impl From<snp_proto::UpdateVmReq> for UpdateVMReq {
|
||||
fn from(req: snp_proto::UpdateVmReq) -> Self {
|
||||
Self {
|
||||
uuid: req.uuid,
|
||||
vcpus: req.vcpus as usize,
|
||||
@ -537,10 +533,9 @@ impl VM {
|
||||
return Err(VMCreationErrors::DiskTooSmall);
|
||||
}
|
||||
|
||||
if let Err(ovmf_err) = res.find_or_download_file(
|
||||
crate::constants::OVMF_URL.to_string(),
|
||||
crate::constants::OVMF_HASH.to_string(),
|
||||
) {
|
||||
if let Err(ovmf_err) =
|
||||
res.find_or_download_file(OVMF_URL.to_string(), OVMF_HASH.to_string())
|
||||
{
|
||||
return Err(VMCreationErrors::BootFileError(format!(
|
||||
"Could not get OVMF: {ovmf_err:?}"
|
||||
)));
|
||||
|
Loading…
Reference in New Issue
Block a user