105 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
// SPDX-License-Identifier: Apache-2.0
 | 
						|
 | 
						|
use super::grpc::{self, proto};
 | 
						|
use super::{injector, Dtrfs, Error};
 | 
						|
use crate::config::Config;
 | 
						|
use crate::utils::block_on;
 | 
						|
use log::{debug, info};
 | 
						|
 | 
						|
#[derive(Clone, Debug, Default, PartialEq)]
 | 
						|
pub struct Request {
 | 
						|
    hostname: String,
 | 
						|
    vcpus: u32,
 | 
						|
    memory_mib: u32,
 | 
						|
    disk_size_mib: u32,
 | 
						|
    dtrfs: Option<Dtrfs>,
 | 
						|
}
 | 
						|
 | 
						|
impl Request {
 | 
						|
    pub fn process_request(
 | 
						|
        hostname: String,
 | 
						|
        uuid: &str,
 | 
						|
        vcpus: u32,
 | 
						|
        memory_mb: u32,
 | 
						|
        disk_size_gb: u32,
 | 
						|
        dtrfs: &str,
 | 
						|
    ) -> Result<(), Error> {
 | 
						|
        let dtrfs = match dtrfs {
 | 
						|
            "" => None,
 | 
						|
            "latest" => Some(super::DEFAULT_DTRFS.clone()),
 | 
						|
            path => {
 | 
						|
                log::info!("Loading DTRFS from path: {path}");
 | 
						|
                Some(Dtrfs::load_from_file(path)?)
 | 
						|
            }
 | 
						|
        };
 | 
						|
        let req =
 | 
						|
            Self { hostname, vcpus, memory_mib: memory_mb, disk_size_mib: disk_size_gb, dtrfs };
 | 
						|
        if req == Self::default() {
 | 
						|
            log::info!("Skipping hardware upgrade (no arguments specified).");
 | 
						|
            return Ok(());
 | 
						|
        }
 | 
						|
        log::info!("Starting VM updated based on req: {req:#?}");
 | 
						|
        req.update(uuid)
 | 
						|
    }
 | 
						|
 | 
						|
    fn update(&self, uuid: &str) -> Result<(), Error> {
 | 
						|
        info!("Starting the process of updating the VM. {self:?}");
 | 
						|
        let update_vm_resp = self.send_update_vm_request(uuid)?;
 | 
						|
        debug!("The response for Update VM is: {update_vm_resp:#?}");
 | 
						|
        if !update_vm_resp.error.is_empty() {
 | 
						|
            return Err(Error::Node(update_vm_resp.error));
 | 
						|
        }
 | 
						|
 | 
						|
        eprintln!("The modifications got approved. Proceeding with update...");
 | 
						|
        let updated_contract = block_on(grpc::get_contract_by_uuid(uuid))?;
 | 
						|
        debug!("Got the current contract for the VM after update. {updated_contract:#?}");
 | 
						|
 | 
						|
        if !(self.vcpus != 0 || self.memory_mib != 0 || self.dtrfs.is_some()) {
 | 
						|
            eprintln!("vCPUs and kernel did not get modified. Secret injection is not required.");
 | 
						|
            return Ok(());
 | 
						|
        }
 | 
						|
 | 
						|
        let args = update_vm_resp.args.ok_or(Error::NoMeasurement)?;
 | 
						|
        let measurement_args = injector::Args {
 | 
						|
            uuid: update_vm_resp.uuid,
 | 
						|
            vcpus: updated_contract.vcpus,
 | 
						|
            kernel: updated_contract.kernel_sha,
 | 
						|
            initrd: updated_contract.dtrfs_sha,
 | 
						|
            args: args.clone(),
 | 
						|
        };
 | 
						|
        let measurement = measurement_args.get_measurement()?;
 | 
						|
 | 
						|
        injector::execute(measurement, args.dtrfs_api_endpoint, None, &updated_contract.hostname)?;
 | 
						|
 | 
						|
        Ok(())
 | 
						|
    }
 | 
						|
 | 
						|
    // returns node IP and data regarding the new VM
 | 
						|
    fn send_update_vm_request(&self, uuid: &str) -> Result<proto::UpdateVmResp, Error> {
 | 
						|
        let (kernel_url, kernel_sha, dtrfs_url, dtrfs_sha) = match self.dtrfs.clone() {
 | 
						|
            Some(dtrfs) => (dtrfs.kernel_url, dtrfs.kernel_sha, dtrfs.dtrfs_url, dtrfs.dtrfs_sha),
 | 
						|
            None => (String::new(), String::new(), String::new(), String::new()),
 | 
						|
        };
 | 
						|
        Ok(block_on(grpc::update_vm(proto::UpdateVmReq {
 | 
						|
            uuid: uuid.to_string(),
 | 
						|
            hostname: self.hostname.clone(),
 | 
						|
            admin_pubkey: Config::get_detee_wallet()?,
 | 
						|
            disk_size_mib: self.disk_size_mib * 1024,
 | 
						|
            vcpus: self.vcpus,
 | 
						|
            memory_mib: self.memory_mib * 1024,
 | 
						|
            kernel_url,
 | 
						|
            kernel_sha,
 | 
						|
            dtrfs_url,
 | 
						|
            dtrfs_sha,
 | 
						|
        }))?)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
pub fn expand_vm_hours(uuid: &str, hours: u32) -> Result<(), Error> {
 | 
						|
    let contract = super::get_one_contract(uuid)?;
 | 
						|
    // vcpus: u32, memory_mb: u32, disk_size_gb: u32, public_ipv4: bool, hours: u32, node_price:
 | 
						|
    let locked_nano = contract.nano_per_minute * 60 * (hours as u64);
 | 
						|
    block_on(grpc::extend_vm(uuid.to_string(), Config::get_detee_wallet()?, locked_nano))?;
 | 
						|
    Ok(())
 | 
						|
}
 |