feat: automatically delete expired vms on client
This commit is contained in:
@ -45,6 +45,9 @@ pub trait VmHostClient: Send + Sync {
|
||||
/// Spawn a VM
|
||||
async fn create_vm(&self, cfg: &FullVmInfo) -> Result<()>;
|
||||
|
||||
/// Delete a VM
|
||||
async fn delete_vm(&self, vm: &Vm) -> Result<()>;
|
||||
|
||||
/// Re-install a vm OS
|
||||
async fn reinstall_vm(&self, cfg: &FullVmInfo) -> Result<()>;
|
||||
|
||||
|
@ -611,6 +611,32 @@ impl VmHostClient for ProxmoxClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_vm(&self, vm: &Vm) -> Result<()> {
|
||||
let vm_id: ProxmoxVmId = vm.id.into();
|
||||
|
||||
// NOT IMPLEMENTED
|
||||
//let t = self.delete_vm(&self.node, vm_id).await?;
|
||||
//self.wait_for_task(&t).await?;
|
||||
|
||||
if let Some(ssh) = &self.ssh {
|
||||
let mut ses = SshClient::new()?;
|
||||
ses.connect(
|
||||
(self.api.base().host().unwrap().to_string(), 22),
|
||||
&ssh.user,
|
||||
&ssh.key,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let cmd = format!("/usr/sbin/qm destroy {}", vm_id,);
|
||||
let (code, rsp) = ses.execute(cmd.as_str()).await?;
|
||||
info!("{}", rsp);
|
||||
if code != 0 {
|
||||
bail!("Failed to destroy vm, exit-code {}, {}", code, rsp);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn reinstall_vm(&self, req: &FullVmInfo) -> Result<()> {
|
||||
let vm_id = req.vm.id.into();
|
||||
|
||||
@ -1198,7 +1224,7 @@ mod tests {
|
||||
enabled: true,
|
||||
release_date: Utc::now(),
|
||||
url: "http://localhost.com/ubuntu_server_24.04.img".to_string(),
|
||||
default_username: None
|
||||
default_username: None,
|
||||
},
|
||||
ips: vec![
|
||||
VmIpAssignment {
|
||||
|
24
src/mocks.rs
24
src/mocks.rs
@ -1,14 +1,21 @@
|
||||
#![allow(unused)]
|
||||
use crate::dns::{BasicRecord, DnsServer, RecordType};
|
||||
use crate::exchange::{ExchangeRateService, Ticker, TickerRate};
|
||||
use crate::host::{FullVmInfo, TerminalStream, TimeSeries, TimeSeriesData, VmHostClient, VmHostInfo};
|
||||
use crate::host::{
|
||||
FullVmInfo, TerminalStream, TimeSeries, TimeSeriesData, VmHostClient, VmHostInfo,
|
||||
};
|
||||
use crate::lightning::{AddInvoiceRequest, AddInvoiceResult, InvoiceUpdate, LightningNode};
|
||||
use crate::router::{ArpEntry, Router};
|
||||
use crate::status::{VmRunningState, VmState};
|
||||
use anyhow::{anyhow, bail, ensure, Context};
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use fedimint_tonic_lnd::tonic::codegen::tokio_stream::Stream;
|
||||
use lnvps_db::{async_trait, AccessPolicy, DiskInterface, DiskType, IpRange, IpRangeAllocationMode, LNVpsDb, OsDistribution, User, UserSshKey, Vm, VmCostPlan, VmCostPlanIntervalType, VmCustomPricing, VmCustomPricingDisk, VmCustomTemplate, VmHost, VmHostDisk, VmHostKind, VmHostRegion, VmIpAssignment, VmOsImage, VmPayment, VmTemplate};
|
||||
use lnvps_db::{
|
||||
async_trait, AccessPolicy, DiskInterface, DiskType, IpRange, IpRangeAllocationMode, LNVpsDb,
|
||||
OsDistribution, User, UserSshKey, Vm, VmCostPlan, VmCostPlanIntervalType, VmCustomPricing,
|
||||
VmCustomPricingDisk, VmCustomTemplate, VmHost, VmHostDisk, VmHostKind, VmHostRegion,
|
||||
VmIpAssignment, VmOsImage, VmPayment, VmTemplate,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Add;
|
||||
use std::pin::Pin;
|
||||
@ -174,7 +181,7 @@ impl Default for MockDb {
|
||||
enabled: true,
|
||||
release_date: Utc::now(),
|
||||
url: "https://example.com/debian_12.img".to_string(),
|
||||
default_username: None
|
||||
default_username: None,
|
||||
},
|
||||
);
|
||||
Self {
|
||||
@ -828,6 +835,12 @@ impl VmHostClient for MockVmHost {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_vm(&self, vm: &Vm) -> anyhow::Result<()> {
|
||||
let mut vms = self.vms.lock().await;
|
||||
vms.remove(&vm.id);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn reinstall_vm(&self, cfg: &FullVmInfo) -> anyhow::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
@ -898,7 +911,10 @@ impl DnsServer for MockDnsServer {
|
||||
zones.get_mut(zone_id).unwrap()
|
||||
};
|
||||
|
||||
if table.values().any(|v| v.name == record.name && v.kind == record.kind.to_string()) {
|
||||
if table
|
||||
.values()
|
||||
.any(|v| v.name == record.name && v.kind == record.kind.to_string())
|
||||
{
|
||||
bail!("Duplicate record with name {}", record.name);
|
||||
}
|
||||
|
||||
|
@ -593,8 +593,13 @@ impl LNVpsProvisioner {
|
||||
|
||||
/// Delete a VM and its associated resources
|
||||
pub async fn delete_vm(&self, vm_id: u64) -> Result<()> {
|
||||
// host client currently doesn't support delete (proxmox)
|
||||
// VM should already be stopped by [Worker]
|
||||
let vm = self.db.get_vm(vm_id).await?;
|
||||
let host = self.db.get_host(vm.host_id).await?;
|
||||
|
||||
let client = get_host_client(&host, &self.provisioner_config)?;
|
||||
if let Err(e) = client.delete_vm(&vm).await {
|
||||
warn!("Failed to delete VM: {}", e);
|
||||
}
|
||||
|
||||
self.delete_ip_assignments(vm_id).await?;
|
||||
self.db.delete_vm(vm_id).await?;
|
||||
@ -762,7 +767,12 @@ mod tests {
|
||||
assert_eq!(zones.get("mock-v6-rev-zone-id").unwrap().len(), 1);
|
||||
assert_eq!(zones.get("mock-forward-zone-id").unwrap().len(), 2);
|
||||
|
||||
let v6 = zones.get("mock-v6-rev-zone-id").unwrap().iter().next().unwrap();
|
||||
let v6 = zones
|
||||
.get("mock-v6-rev-zone-id")
|
||||
.unwrap()
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
assert_eq!(v6.1.kind, "PTR");
|
||||
assert!(v6.1.name.ends_with("0.0.d.f.ip6.arpa"));
|
||||
}
|
||||
|
Reference in New Issue
Block a user