160
lnvps_db/Cargo.lock
generated
160
lnvps_db/Cargo.lock
generated
@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
@ -245,41 +245,6 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
@ -291,16 +256,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
@ -394,12 +349,6 @@ dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
@ -508,12 +457,6 @@ version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
@ -725,12 +668,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.0.3"
|
||||
@ -752,17 +689,6 @@ dependencies = [
|
||||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.6.0"
|
||||
@ -771,7 +697,6 @@ checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -840,8 +765,6 @@ dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"serde",
|
||||
"serde_with",
|
||||
"sqlx",
|
||||
"url",
|
||||
]
|
||||
@ -932,12 +855,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
@ -1072,12 +989,6 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.20"
|
||||
@ -1239,36 +1150,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.6.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
@ -1399,7 +1280,7 @@ dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"hashlink",
|
||||
"hex",
|
||||
"indexmap 2.6.0",
|
||||
"indexmap",
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
@ -1579,12 +1460,6 @@ dependencies = [
|
||||
"unicode-properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
@ -1646,37 +1521,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.7.6"
|
||||
|
49
lnvps_db/migrations/20250306113236_custom_pricing.sql
Normal file
49
lnvps_db/migrations/20250306113236_custom_pricing.sql
Normal file
@ -0,0 +1,49 @@
|
||||
-- fix this fk ref
|
||||
ALTER TABLE vm_template DROP FOREIGN KEY fk_template_region;
|
||||
alter table vm_template
|
||||
add constraint fk_template_region foreign key (region_id) references vm_host_region (id);
|
||||
|
||||
create table vm_custom_pricing
|
||||
(
|
||||
id integer unsigned not null auto_increment primary key,
|
||||
name varchar(100) not null,
|
||||
enabled bit(1) not null,
|
||||
created timestamp default current_timestamp,
|
||||
expires timestamp,
|
||||
region_id integer unsigned not null,
|
||||
currency varchar(5) not null,
|
||||
cpu_cost float not null,
|
||||
memory_cost float not null,
|
||||
ip4_cost float not null,
|
||||
ip6_cost float not null,
|
||||
|
||||
constraint fk_custom_pricing_region foreign key (region_id) references vm_host_region (id)
|
||||
);
|
||||
create table vm_custom_pricing_disk
|
||||
(
|
||||
id integer unsigned not null auto_increment primary key,
|
||||
pricing_id integer unsigned not null,
|
||||
kind smallint unsigned not null,
|
||||
interface smallint unsigned not null,
|
||||
cost float not null,
|
||||
|
||||
constraint fk_custom_pricing_disk foreign key (pricing_id) references vm_custom_pricing (id)
|
||||
);
|
||||
ALTER TABLE vm MODIFY COLUMN template_id int (10) unsigned NULL;
|
||||
ALTER TABLE vm
|
||||
add COLUMN custom_template_id int(10) unsigned NULL;
|
||||
|
||||
create table vm_custom_template
|
||||
(
|
||||
id integer unsigned not null auto_increment primary key,
|
||||
cpu tinyint unsigned not null,
|
||||
memory bigint unsigned not null,
|
||||
disk_size bigint unsigned not null,
|
||||
disk_type smallint unsigned not null,
|
||||
disk_interface smallint unsigned not null,
|
||||
pricing_id integer unsigned not null,
|
||||
|
||||
constraint fk_custom_template_pricing foreign key (pricing_id) references vm_custom_pricing (id)
|
||||
);
|
||||
alter table vm
|
||||
add constraint fk_vm_custom_template foreign key (custom_template_id) references vm_custom_template (id);
|
@ -139,4 +139,19 @@ pub trait LNVpsDb: Sync + Send {
|
||||
|
||||
/// Return the most recently settled invoice
|
||||
async fn last_paid_invoice(&self) -> Result<Option<VmPayment>>;
|
||||
|
||||
/// Return the list of active custom pricing models for a given region
|
||||
async fn list_custom_pricing(&self, region_id: u64) -> Result<Vec<VmCustomPricing>>;
|
||||
|
||||
/// Get a custom pricing model
|
||||
async fn get_custom_pricing(&self, id: u64) -> Result<VmCustomPricing>;
|
||||
|
||||
/// Get a custom pricing model
|
||||
async fn get_custom_vm_template(&self, id: u64) -> Result<VmCustomTemplate>;
|
||||
|
||||
/// Insert custom vm template
|
||||
async fn insert_custom_vm_template(&self, template: &VmCustomTemplate) -> Result<u64>;
|
||||
|
||||
/// Return the list of disk prices for a given custom pricing model
|
||||
async fn list_custom_pricing_disk(&self, pricing_id: u64) -> Result<Vec<VmCustomPricingDisk>>;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ pub struct VmHostDisk {
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, sqlx::Type, Default, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, sqlx::Type, Default, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
pub enum DiskType {
|
||||
#[default]
|
||||
@ -100,7 +100,7 @@ pub enum DiskType {
|
||||
SSD = 1,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, sqlx::Type, Default, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, sqlx::Type, Default, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
pub enum DiskInterface {
|
||||
#[default]
|
||||
@ -109,7 +109,7 @@ pub enum DiskInterface {
|
||||
PCIe = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, sqlx::Type, Default, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, sqlx::Type, Default, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
pub enum OsDistribution {
|
||||
#[default]
|
||||
@ -203,6 +203,50 @@ pub struct VmTemplate {
|
||||
pub region_id: u64,
|
||||
}
|
||||
|
||||
/// A custom pricing template, used for billing calculation of a specific VM
|
||||
/// This mostly just stores the number of resources assigned and the specific pricing used
|
||||
#[derive(FromRow, Clone, Debug, Default)]
|
||||
pub struct VmCustomTemplate {
|
||||
pub id: u64,
|
||||
pub cpu: u16,
|
||||
pub memory: u64,
|
||||
pub disk_size: u64,
|
||||
pub disk_type: DiskType,
|
||||
pub disk_interface: DiskInterface,
|
||||
pub pricing_id: u64,
|
||||
}
|
||||
|
||||
/// Custom pricing template, usually 1 per region
|
||||
#[derive(FromRow, Clone, Debug, Default)]
|
||||
pub struct VmCustomPricing {
|
||||
pub id: u64,
|
||||
pub name: String,
|
||||
pub enabled: bool,
|
||||
pub created: DateTime<Utc>,
|
||||
pub expires: Option<DateTime<Utc>>,
|
||||
pub region_id: u64,
|
||||
pub currency: String,
|
||||
/// Cost per CPU core
|
||||
pub cpu_cost: f32,
|
||||
/// Cost per GB ram
|
||||
pub memory_cost: f32,
|
||||
/// Cost per IPv4 address
|
||||
pub ip4_cost: f32,
|
||||
/// Cost per IPv6 address
|
||||
pub ip6_cost: f32,
|
||||
}
|
||||
|
||||
/// Pricing per GB on a disk type (SSD/HDD)
|
||||
#[derive(FromRow, Clone, Debug, Default)]
|
||||
pub struct VmCustomPricingDisk {
|
||||
pub id: u64,
|
||||
pub pricing_id: u64,
|
||||
pub kind: DiskType,
|
||||
pub interface: DiskInterface,
|
||||
/// Cost as per the currency of the [VmCustomPricing::currency]
|
||||
pub cost: f32,
|
||||
}
|
||||
|
||||
#[derive(FromRow, Clone, Debug, Default)]
|
||||
pub struct Vm {
|
||||
/// Unique VM ID (Same in proxmox)
|
||||
@ -213,8 +257,10 @@ pub struct Vm {
|
||||
pub user_id: u64,
|
||||
/// The base image of this VM
|
||||
pub image_id: u64,
|
||||
/// The base image of this VM
|
||||
pub template_id: u64,
|
||||
/// The base image of this VM [VmTemplate]
|
||||
pub template_id: Option<u64>,
|
||||
/// Custom pricing specification used for this vm [VmCustomTemplate]
|
||||
pub custom_template_id: Option<u64>,
|
||||
/// Users ssh-key assigned to this VM
|
||||
pub ssh_key_id: u64,
|
||||
/// When the VM was created
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
IpRange, LNVpsDb, User, UserSshKey, Vm, VmCostPlan, VmHost, VmHostDisk, VmHostRegion,
|
||||
VmIpAssignment, VmOsImage, VmPayment, VmTemplate,
|
||||
IpRange, LNVpsDb, User, UserSshKey, Vm, VmCostPlan, VmCustomPricing, VmCustomPricingDisk,
|
||||
VmCustomTemplate, VmHost, VmHostDisk, VmHostRegion, VmIpAssignment, VmOsImage, VmPayment,
|
||||
VmTemplate,
|
||||
};
|
||||
use anyhow::{bail, Error, Result};
|
||||
use async_trait::async_trait;
|
||||
@ -27,7 +28,9 @@ impl LNVpsDbMysql {
|
||||
#[async_trait]
|
||||
impl LNVpsDb for LNVpsDbMysql {
|
||||
async fn migrate(&self) -> Result<()> {
|
||||
sqlx::migrate!().run(&self.db).await.map_err(Error::new)
|
||||
let migrator = sqlx::migrate!();
|
||||
migrator.run(&self.db).await.map_err(Error::new)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn upsert_user(&self, pubkey: &[u8; 32]) -> Result<u64> {
|
||||
@ -210,7 +213,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
||||
}
|
||||
|
||||
async fn list_vm_templates(&self) -> Result<Vec<VmTemplate>> {
|
||||
sqlx::query_as("select * from vm_template")
|
||||
sqlx::query_as("select * from vm_template where enabled = 1")
|
||||
.fetch_all(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
@ -219,14 +222,14 @@ impl LNVpsDb for LNVpsDbMysql {
|
||||
async fn insert_vm_template(&self, template: &VmTemplate) -> Result<u64> {
|
||||
Ok(sqlx::query("insert into vm_template(name,enabled,created,expires,cpu,memory,disk_size,disk_type,disk_interface,cost_plan_id,region_id) values(?,?,?,?,?,?,?,?,?,?,?) returning id")
|
||||
.bind(&template.name)
|
||||
.bind(&template.enabled)
|
||||
.bind(&template.created)
|
||||
.bind(&template.expires)
|
||||
.bind(template.enabled)
|
||||
.bind(template.created)
|
||||
.bind(template.expires)
|
||||
.bind(template.cpu)
|
||||
.bind(template.memory)
|
||||
.bind(template.disk_size)
|
||||
.bind(&template.disk_type)
|
||||
.bind(&template.disk_interface)
|
||||
.bind(template.disk_type)
|
||||
.bind(template.disk_interface)
|
||||
.bind(template.cost_plan_id)
|
||||
.bind(template.region_id)
|
||||
.fetch_one(&self.db)
|
||||
@ -274,11 +277,12 @@ impl LNVpsDb for LNVpsDbMysql {
|
||||
}
|
||||
|
||||
async fn insert_vm(&self, vm: &Vm) -> Result<u64> {
|
||||
Ok(sqlx::query("insert into vm(host_id,user_id,image_id,template_id,ssh_key_id,created,expires,disk_id,mac_address,ref_code) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) returning id")
|
||||
Ok(sqlx::query("insert into vm(host_id,user_id,image_id,template_id,custom_template_id,ssh_key_id,created,expires,disk_id,mac_address,ref_code) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) returning id")
|
||||
.bind(vm.host_id)
|
||||
.bind(vm.user_id)
|
||||
.bind(vm.image_id)
|
||||
.bind(vm.template_id)
|
||||
.bind(vm.custom_template_id)
|
||||
.bind(vm.ssh_key_id)
|
||||
.bind(vm.created)
|
||||
.bind(vm.expires)
|
||||
@ -343,7 +347,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
||||
.bind(&ip_assignment.dns_forward_ref)
|
||||
.bind(&ip_assignment.dns_reverse)
|
||||
.bind(&ip_assignment.dns_reverse_ref)
|
||||
.bind(&ip_assignment.id)
|
||||
.bind(ip_assignment.id)
|
||||
.execute(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)?;
|
||||
@ -368,7 +372,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
||||
|
||||
async fn delete_vm_ip_assignment(&self, vm_id: u64) -> Result<()> {
|
||||
sqlx::query("update vm_ip_assignment set deleted = 1 where vm_id = ?")
|
||||
.bind(&vm_id)
|
||||
.bind(vm_id)
|
||||
.execute(&self.db)
|
||||
.await?;
|
||||
Ok(())
|
||||
@ -448,4 +452,50 @@ impl LNVpsDb for LNVpsDbMysql {
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
async fn list_custom_pricing(&self, region_id: u64) -> Result<Vec<VmCustomPricing>> {
|
||||
sqlx::query_as("select * from vm_custom_pricing where region_id = ? and enabled = 1")
|
||||
.bind(region_id)
|
||||
.fetch_all(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
async fn get_custom_pricing(&self, id: u64) -> Result<VmCustomPricing> {
|
||||
sqlx::query_as("select * from vm_custom_pricing where id=?")
|
||||
.bind(id)
|
||||
.fetch_one(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
async fn get_custom_vm_template(&self, id: u64) -> Result<VmCustomTemplate> {
|
||||
sqlx::query_as("select * from vm_custom_template where id=?")
|
||||
.bind(id)
|
||||
.fetch_one(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
async fn insert_custom_vm_template(&self, template: &VmCustomTemplate) -> Result<u64> {
|
||||
Ok(sqlx::query("insert into vm_custom_template(cpu,memory,disk_size,disk_type,disk_interface,pricing_id) values(?,?,?,?,?,?) returning id")
|
||||
.bind(template.cpu)
|
||||
.bind(template.memory)
|
||||
.bind(template.disk_size)
|
||||
.bind(template.disk_type)
|
||||
.bind(template.disk_interface)
|
||||
.bind(template.pricing_id)
|
||||
.fetch_one(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)?
|
||||
.try_get(0)?)
|
||||
}
|
||||
|
||||
async fn list_custom_pricing_disk(&self, pricing_id: u64) -> Result<Vec<VmCustomPricingDisk>> {
|
||||
sqlx::query_as("select * from vm_custom_pricing_disk where pricing_id=?")
|
||||
.bind(pricing_id)
|
||||
.fetch_all(&self.db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user