You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
9.7 KiB
298 lines
9.7 KiB
use ureq;
|
|
use crate::success;
|
|
use crate::external;
|
|
|
|
use serde_json;
|
|
use serde::{Serialize, Deserialize};
|
|
use serde_with::{
|
|
DisplayFromStr,
|
|
serde_as,
|
|
};
|
|
use uuid;
|
|
|
|
/// Defines a VM (used for requests using the VM section)
|
|
#[serde_as]
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
pub struct VirtualMachine {
|
|
#[serde_as(as="DisplayFromStr")]
|
|
vm_id: uuid::Uuid, // should be UUIDv4
|
|
name: String, // the name set by the user
|
|
#[serde_as(as="DisplayFromStr")]
|
|
plan_id: i32, // should be more strict
|
|
hostname: String, // the hostname set by the user
|
|
#[serde(rename="primaryip")]
|
|
primary_ip: std::net::Ipv4Addr,
|
|
#[serde(rename="privateip")]
|
|
private_ip: std::net::Ipv4Addr,
|
|
#[serde_as(as="DisplayFromStr")]
|
|
ram: i32, // in GB, may need to be a float
|
|
#[serde_as(as="DisplayFromStr")]
|
|
vcpu: i32, // CPU cores
|
|
#[serde_as(as="DisplayFromStr")]
|
|
storage: i32, // in GB
|
|
#[serde_as(as="DisplayFromStr")]
|
|
bandwidth: i32, // in GB/month
|
|
region: String, // could be more strict
|
|
os_status: String, // should be nmore strict
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct VMListResponse {
|
|
vms: Vec<VirtualMachine>,
|
|
#[serde(with="success")]
|
|
success: bool, // should be more strict "yes" or "no" as optiobs
|
|
}
|
|
|
|
#[serde_as]
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct VMInfoExtra {
|
|
#[serde_as(as="DisplayFromStr")]
|
|
/// bandwidth allowed over a month in GB
|
|
bandwidth: i32,
|
|
/// the hostname set by the user
|
|
hostname: String, // sufficiently vague
|
|
/// the name set by the user
|
|
name: String, // sufficiently vague
|
|
/// the status of the operating system; possible values: "active", ... TODO
|
|
os_status: String, // should be stricter
|
|
#[serde_as(as="DisplayFromStr")]
|
|
/// id of the plan being used on the VM
|
|
plan_id: i32,
|
|
#[serde(rename="primaryip")]
|
|
/// primary (floating) IP
|
|
primary_ip: std::net::Ipv4Addr,
|
|
#[serde(rename="privateip")]
|
|
/// the private (non-floating) IP to connect between nodes
|
|
private_ip: std::net::Ipv4Addr,
|
|
#[serde_as(as="DisplayFromStr")]
|
|
/// RAM meassured in MB
|
|
ram: i32,
|
|
/// the datacentre location the VM is running in
|
|
region: LNRegion,
|
|
#[serde_as(as="DisplayFromStr")]
|
|
/// the storage size of the VM in GB
|
|
storage: i32,
|
|
#[serde_as(as="DisplayFromStr")]
|
|
/// number of virtual CPU cores allocated to the VM
|
|
vcpu: i32,
|
|
#[serde_as(as="DisplayFromStr")]
|
|
/// UUIDv4 of the VM
|
|
vm_id: uuid::Uuid,
|
|
}
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
#[serde(untagged)]
|
|
pub enum IPAddress {
|
|
V4(std::net::Ipv4Addr),
|
|
V6(std::net::Ipv6Addr),
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
// TODO: (de)serialize as "4"/"6" respectively
|
|
pub enum IPAddressType {
|
|
#[serde(rename="4")]
|
|
V4,
|
|
#[serde(rename="6")]
|
|
V6,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct VMAddress {
|
|
addr: IPAddress,
|
|
#[serde(with="external")]
|
|
external: bool,
|
|
version: IPAddressType,
|
|
reverse: Option<String>, // optional rDNS; string is sufficient, since the server will not be able to set it to something invalid.
|
|
}
|
|
|
|
#[serde_as]
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct VMInfo {
|
|
#[serde(rename="additionalip")]
|
|
additional_ip: Vec<VMAddress>,
|
|
#[serde(rename="additionalprivateip")]
|
|
additional_private_ip: Vec<VMAddress>,
|
|
addresses: Vec<VMAddress>,
|
|
/// a possibly empty string containing an error message
|
|
error_detail: Option<String>,
|
|
/// some unkown string that doesn't seem to be a UUID... maybe the checksum?
|
|
host_id: String,
|
|
/// the name of the VM set at creation by the user
|
|
hostname: String,
|
|
/// the name of the image being used by the VM
|
|
image: String,
|
|
/// the primary, external IP of the VM
|
|
ip: std::net::Ipv4Addr,
|
|
/// a list of IPv6 addresses assigned to the VM
|
|
ipv6: Vec<std::net::Ipv6Addr>,
|
|
/// Login details from the VM; this could potentially be a bit more strict to support the storing of username and password separately.
|
|
/// Also, it's optional. The server may not even report this value at all, not only give a blank one. Fair enough. Seems more secure.
|
|
login_details: Option<String>,
|
|
/// the operating system (orignal image used to load the machine)
|
|
os: String, // sufficiently vague
|
|
#[serde(rename="privateip")]
|
|
/// the primary private IP assigned to the machine
|
|
private_ip: std::net::Ipv4Addr,
|
|
/// security groups by id that the VM belongs to; should be a vec of i32, but it might take some custom implementations
|
|
security_group_ids: Vec<String>,
|
|
/// security groups by name that the VM belongs to
|
|
security_groups: Vec<String>,
|
|
#[serde(rename="securitygroups")]
|
|
/// why is there a second one of these with a different name. This is stupid.
|
|
security_groups2: Vec<String>,
|
|
/// an HTML status of the machine
|
|
status: String,
|
|
/// the color of the status; this could be stricter
|
|
status_color: String, // could be more strict
|
|
/// the non-HTML status, this could potentially be more strict
|
|
status_nohtml: String,
|
|
/// A raw status-code string; this could for sure be more strict.
|
|
status_raw: String,
|
|
/// A possibly empty string, idk what task_state is tho
|
|
task_state: String, // a possibly empty string
|
|
/// A possibly empty string of attached volumes.
|
|
volumes: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct VMInfoResponse {
|
|
extra: VMInfoExtra,
|
|
info: VMInfo,
|
|
#[serde(with="success")]
|
|
success: bool,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub enum LNPlanCategory {
|
|
#[serde(rename="Compute-Optimized")]
|
|
ComputeOptimized,
|
|
#[serde(rename="General Purpose")]
|
|
GeneralPurpose,
|
|
#[serde(rename="Memory-Optimized")]
|
|
MemoryOptimized,
|
|
#[serde(rename="SSD-Cached High-Memory")]
|
|
SSDCacheHighMemory,
|
|
#[serde(rename="SSD-Cached Standard")]
|
|
SSDCacheStandard,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum LNRegion {
|
|
Montreal,
|
|
Roubaix,
|
|
Toronto
|
|
}
|
|
|
|
#[serde_as]
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct LNPlan {
|
|
#[serde_as(as="DisplayFromStr")]
|
|
all_regions: i32, // may need to be more strict?
|
|
#[serde_as(as="DisplayFromStr")]
|
|
bandwidth: i32, // in Mbps
|
|
category: LNPlanCategory, // could be more strict, "General Purpose", "Compute Optimized", "RAM Optimized"
|
|
#[serde_as(as="DisplayFromStr")]
|
|
cpu_points: f32, // no idea what this meas
|
|
name: String, // plan name, this could potentially be strictly typed as the types of plans don't often change "s.half", "s.1", "m.1", "m.2", etc.
|
|
#[serde_as(as="DisplayFromStr")]
|
|
plan_id: i32, // can be strictly typed, if needed
|
|
#[serde_as(as="DisplayFromStr")]
|
|
price: f32, // up to 7 decmial points (f32), and this is the number of US dollars per hour
|
|
price_monthly_nice: String, // instead of calculating it on your own, this provides a nice reading of the price for clients
|
|
price_nice: String, // same as above, but for the hour
|
|
#[serde_as(as="DisplayFromStr")]
|
|
ram: i32, // in MB
|
|
regions: Vec<LNRegion>, // list of regions by name
|
|
regions_nice: String, // list of regions concatonated with commans
|
|
#[serde_as(as="DisplayFromStr")]
|
|
storage: i32, // per GB
|
|
#[serde_as(as="DisplayFromStr")]
|
|
vcpu: i32, // number of vCPU cores
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct PlanListResponse {
|
|
plans: Vec<LNPlan>,
|
|
#[serde(with="success")]
|
|
success: bool, // should be more strict: "yes" or "no" as options
|
|
}
|
|
|
|
#[serde_as]
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct LNImage {
|
|
#[serde_as(as="DisplayFromStr")]
|
|
image_id: i32, // id of the image
|
|
name: String, // set by the user or LunaNode
|
|
region: LNRegion,
|
|
status: String, // should be stricter, at least "active", "inactive"(?)
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct LNImageDetails {
|
|
cache_mode: String, // should be stricter, at least "writeback",
|
|
checksum: String, // should be stricter, to check of checksum type
|
|
disk_format: String, // should be stricter, at least "iso"
|
|
hw_disk_bus: String, // should be stricter, at least "ide",
|
|
hw_video_model: String, // could, in theory, be stricter, at least: "cirrus",
|
|
hw_vif_model: String, // appropriately vague
|
|
#[serde(with="success")]
|
|
is_read_only: bool, // "yes"/"no"
|
|
libvrt_cpu_mode: String, // should be stricter, at least: "host-model",
|
|
metadata: Vec<()>, // vec of what?
|
|
name: String, // sufficiently vague
|
|
region: LNRegion, // sufficiently typed
|
|
size: i32, // in MB, maybe?
|
|
status: String, // should be stricter, at least: "active",
|
|
time_created: String, // should be a datetime
|
|
}
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct LNImageDetailResponse {
|
|
#[serde(with="success")]
|
|
success: bool,
|
|
details: LNImageDetails,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct LNImageListResponse {
|
|
images: Vec<LNImage>,
|
|
}
|
|
|
|
#[serde_as]
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct BillingCreditResponse {
|
|
/// Money left in the account in USD
|
|
#[serde_as(as="DisplayFromStr")]
|
|
credit: f32,
|
|
#[serde(with="success")]
|
|
success: bool, // this should be stricter
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct LunaNodeErrorResponse {
|
|
#[serde(with="success")]
|
|
success: bool,
|
|
error: String, // proper type, full accoutnign of the error from the API
|
|
}
|
|
impl std::fmt::Display for LunaNodeErrorResponse {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(f, "An API error has occured! {}", self.error)
|
|
}
|
|
}
|
|
impl std::error::Error for LunaNodeErrorResponse {}
|
|
|
|
#[derive(Debug)]
|
|
pub enum LunaNodeError {
|
|
RequestError(ureq::Error),
|
|
DeserializationError(std::io::Error),
|
|
TimeError(std::time::SystemTimeError),
|
|
LunaNodeError(LunaNodeErrorResponse),
|
|
SerdeError(serde_json::Error, String), // the serde error, accompanied by a raw string
|
|
GetFuckedError,
|
|
}
|
|
impl std::fmt::Display for LunaNodeError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(f, "An error has occured! {}", self)
|
|
}
|
|
}
|
|
impl std::error::Error for LunaNodeError {}
|