feat: readonly mode
This commit is contained in:
parent
76241cc08b
commit
e6c3b4e063
@ -1,5 +1,6 @@
|
|||||||
# MySQL database connection string
|
# MySQL database connection string
|
||||||
db: "mysql://root:root@localhost:3376/lnvps"
|
db: "mysql://root:root@localhost:3376/lnvps"
|
||||||
|
read_only: true
|
||||||
lnd:
|
lnd:
|
||||||
url: "https://127.0.0.1:10003"
|
url: "https://127.0.0.1:10003"
|
||||||
cert: "/home/kieran/.polar/networks/2/volumes/lnd/alice/tls.cert"
|
cert: "/home/kieran/.polar/networks/2/volumes/lnd/alice/tls.cert"
|
||||||
|
23
src/api.rs
23
src/api.rs
@ -69,7 +69,11 @@ struct ApiVmStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/api/v1/vm")]
|
#[get("/api/v1/vm")]
|
||||||
async fn v1_list_vms(auth: Nip98Auth, db: &State<Box<dyn LNVpsDb>>, vm_state: &State<VmStateCache>) -> ApiResult<Vec<ApiVmStatus>> {
|
async fn v1_list_vms(
|
||||||
|
auth: Nip98Auth,
|
||||||
|
db: &State<Box<dyn LNVpsDb>>,
|
||||||
|
vm_state: &State<VmStateCache>,
|
||||||
|
) -> ApiResult<Vec<ApiVmStatus>> {
|
||||||
let pubkey = auth.event.pubkey.to_bytes();
|
let pubkey = auth.event.pubkey.to_bytes();
|
||||||
let uid = db.upsert_user(&pubkey).await?;
|
let uid = db.upsert_user(&pubkey).await?;
|
||||||
let mut vms = db.list_user_vms(uid).await?;
|
let mut vms = db.list_user_vms(uid).await?;
|
||||||
@ -81,17 +85,19 @@ async fn v1_list_vms(auth: Nip98Auth, db: &State<Box<dyn LNVpsDb>>, vm_state: &S
|
|||||||
}
|
}
|
||||||
|
|
||||||
let state = vm_state.get_state(vm.id).await;
|
let state = vm_state.get_state(vm.id).await;
|
||||||
ret.push(ApiVmStatus {
|
ret.push(ApiVmStatus { vm, status: state });
|
||||||
vm,
|
|
||||||
status: state,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiData::ok(ret)
|
ApiData::ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/api/v1/vm/<id>")]
|
#[get("/api/v1/vm/<id>")]
|
||||||
async fn v1_get_vm(auth: Nip98Auth, db: &State<Box<dyn LNVpsDb>>, vm_state: &State<VmStateCache>, id: u64) -> ApiResult<ApiVmStatus> {
|
async fn v1_get_vm(
|
||||||
|
auth: Nip98Auth,
|
||||||
|
db: &State<Box<dyn LNVpsDb>>,
|
||||||
|
vm_state: &State<VmStateCache>,
|
||||||
|
id: u64,
|
||||||
|
) -> ApiResult<ApiVmStatus> {
|
||||||
let pubkey = auth.event.pubkey.to_bytes();
|
let pubkey = auth.event.pubkey.to_bytes();
|
||||||
let uid = db.upsert_user(&pubkey).await?;
|
let uid = db.upsert_user(&pubkey).await?;
|
||||||
let mut vm = db.get_vm(id).await?;
|
let mut vm = db.get_vm(id).await?;
|
||||||
@ -103,10 +109,7 @@ async fn v1_get_vm(auth: Nip98Auth, db: &State<Box<dyn LNVpsDb>>, vm_state: &Sta
|
|||||||
t.hydrate_up(db).await?;
|
t.hydrate_up(db).await?;
|
||||||
}
|
}
|
||||||
let state = vm_state.get_state(vm.id).await;
|
let state = vm_state.get_state(vm.id).await;
|
||||||
ApiData::ok(ApiVmStatus {
|
ApiData::ok(ApiVmStatus { vm, status: state })
|
||||||
vm,
|
|
||||||
status: state,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/api/v1/image")]
|
#[get("/api/v1/image")]
|
||||||
|
@ -18,6 +18,7 @@ use std::time::Duration;
|
|||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub db: String,
|
pub db: String,
|
||||||
pub lnd: LndConfig,
|
pub lnd: LndConfig,
|
||||||
|
pub read_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
@ -49,7 +50,7 @@ async fn main() -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let status = VmStateCache::new();
|
let status = VmStateCache::new();
|
||||||
let mut worker = Worker::new(db.clone(), lnd.clone(), status.clone());
|
let mut worker = Worker::new(config.read_only, db.clone(), lnd.clone(), status.clone());
|
||||||
let sender = worker.sender();
|
let sender = worker.sender();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
|
@ -4,5 +4,5 @@ pub mod host;
|
|||||||
pub mod invoice;
|
pub mod invoice;
|
||||||
pub mod nip98;
|
pub mod nip98;
|
||||||
pub mod provisioner;
|
pub mod provisioner;
|
||||||
pub mod worker;
|
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
pub mod worker;
|
||||||
|
@ -49,4 +49,4 @@ impl VmStateCache {
|
|||||||
let guard = self.state.read().await;
|
let guard = self.state.read().await;
|
||||||
guard.get(&id).cloned().unwrap_or_default()
|
guard.get(&id).cloned().unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ pub enum WorkJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Worker {
|
pub struct Worker {
|
||||||
|
read_only: bool,
|
||||||
db: Box<dyn LNVpsDb>,
|
db: Box<dyn LNVpsDb>,
|
||||||
lnd: Client,
|
lnd: Client,
|
||||||
provisioner: Box<dyn Provisioner>,
|
provisioner: Box<dyn Provisioner>,
|
||||||
@ -28,10 +29,16 @@ pub struct Worker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Worker {
|
impl Worker {
|
||||||
pub fn new<D: LNVpsDb + Clone + 'static>(db: D, lnd: Client, vm_state_cache: VmStateCache) -> Self {
|
pub fn new<D: LNVpsDb + Clone + 'static>(
|
||||||
|
read_only: bool,
|
||||||
|
db: D,
|
||||||
|
lnd: Client,
|
||||||
|
vm_state_cache: VmStateCache,
|
||||||
|
) -> Self {
|
||||||
let (tx, rx) = unbounded_channel();
|
let (tx, rx) = unbounded_channel();
|
||||||
let p = LNVpsProvisioner::new(db.clone(), lnd.clone());
|
let p = LNVpsProvisioner::new(db.clone(), lnd.clone());
|
||||||
Self {
|
Self {
|
||||||
|
read_only,
|
||||||
db: Box::new(db),
|
db: Box::new(db),
|
||||||
provisioner: Box::new(p),
|
provisioner: Box::new(p),
|
||||||
vm_state_cache,
|
vm_state_cache,
|
||||||
@ -47,6 +54,9 @@ impl Worker {
|
|||||||
|
|
||||||
/// Spawn a VM on the host
|
/// Spawn a VM on the host
|
||||||
async fn spawn_vm(&self, vm: &Vm, vm_host: &VmHost, client: &ProxmoxClient) -> Result<()> {
|
async fn spawn_vm(&self, vm: &Vm, vm_host: &VmHost, client: &ProxmoxClient) -> Result<()> {
|
||||||
|
if self.read_only {
|
||||||
|
bail!("Cant spawn VM's in read-only mode");
|
||||||
|
}
|
||||||
let mut ips = self.db.get_vm_ip_assignments(vm.id).await?;
|
let mut ips = self.db.get_vm_ip_assignments(vm.id).await?;
|
||||||
if ips.is_empty() {
|
if ips.is_empty() {
|
||||||
ips = self.provisioner.allocate_ips(vm.id).await?;
|
ips = self.provisioner.allocate_ips(vm.id).await?;
|
||||||
@ -113,7 +123,7 @@ impl Worker {
|
|||||||
let state = VmState {
|
let state = VmState {
|
||||||
state: match s.status {
|
state: match s.status {
|
||||||
VmStatus::Stopped => VmRunningState::Stopped,
|
VmStatus::Stopped => VmRunningState::Stopped,
|
||||||
VmStatus::Running => VmRunningState::Running
|
VmStatus::Running => VmRunningState::Running,
|
||||||
},
|
},
|
||||||
cpu_usage: s.cpu.unwrap_or(0.0),
|
cpu_usage: s.cpu.unwrap_or(0.0),
|
||||||
mem_usage: s.mem.unwrap_or(0) as f32 / s.max_mem.unwrap_or(1) as f32,
|
mem_usage: s.mem.unwrap_or(0) as f32 / s.max_mem.unwrap_or(1) as f32,
|
||||||
@ -138,7 +148,7 @@ impl Worker {
|
|||||||
match job {
|
match job {
|
||||||
WorkJob::CheckVm { vm_id } => {
|
WorkJob::CheckVm { vm_id } => {
|
||||||
if let Err(e) = self.check_vm(vm_id).await {
|
if let Err(e) = self.check_vm(vm_id).await {
|
||||||
error!("Failed to check VM {}: {:?}", vm_id, e);
|
error!("Failed to check VM {}: {}", vm_id, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WorkJob::SendNotification { .. } => {}
|
WorkJob::SendNotification { .. } => {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user