Simplify RAM management
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
dd7f9176fa
commit
a18310e04a
@ -36,11 +36,11 @@ pub const ALLOWED_DISK_IMAGES_MIME_TYPES: [&str; 2] =
|
||||
/// Disk image max size
|
||||
pub const DISK_IMAGE_MAX_SIZE: FileSize = FileSize::from_gb(10 * 1000);
|
||||
|
||||
/// Min VM memory size (MB)
|
||||
pub const MIN_VM_MEMORY: usize = 100;
|
||||
/// Min VM memory size
|
||||
pub const MIN_VM_MEMORY: FileSize = FileSize::from_mb(100);
|
||||
|
||||
/// Max VM memory size (MB)
|
||||
pub const MAX_VM_MEMORY: usize = 64000;
|
||||
/// Max VM memory size
|
||||
pub const MAX_VM_MEMORY: FileSize = FileSize::from_gb(64);
|
||||
|
||||
/// Disk name min length
|
||||
pub const DISK_NAME_MIN_LEN: usize = 2;
|
||||
|
@ -80,8 +80,8 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
|
||||
vm_title_size: LenConstraints { min: 0, max: 50 },
|
||||
group_id_size: LenConstraints { min: 3, max: 50 },
|
||||
memory_size: LenConstraints {
|
||||
min: constants::MIN_VM_MEMORY,
|
||||
max: constants::MAX_VM_MEMORY,
|
||||
min: constants::MIN_VM_MEMORY.as_bytes(),
|
||||
max: constants::MAX_VM_MEMORY.as_bytes(),
|
||||
},
|
||||
disk_name_size: LenConstraints {
|
||||
min: DISK_NAME_MIN_LEN,
|
||||
|
@ -4,8 +4,8 @@ use crate::libvirt_lib_structures::XMLUuid;
|
||||
use crate::libvirt_lib_structures::domain::*;
|
||||
use crate::libvirt_rest_structures::LibVirtStructError;
|
||||
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction;
|
||||
use crate::utils::file_size_utils::FileSize;
|
||||
use crate::utils::files_utils;
|
||||
use crate::utils::files_utils::convert_size_unit_to_mb;
|
||||
use crate::utils::vm_file_disks_utils::{VMDiskFormat, VMFileDisk};
|
||||
use lazy_regex::regex;
|
||||
use num::Integer;
|
||||
@ -70,8 +70,8 @@ pub struct VMInfo {
|
||||
pub group: Option<VMGroupId>,
|
||||
pub boot_type: BootType,
|
||||
pub architecture: VMArchitecture,
|
||||
/// VM allocated memory, in megabytes
|
||||
pub memory: usize,
|
||||
/// VM allocated RAM memory
|
||||
pub memory: FileSize,
|
||||
/// Number of vCPU for the VM
|
||||
pub number_vcpu: usize,
|
||||
/// Enable VNC access through admin console
|
||||
@ -380,7 +380,7 @@ impl VMInfo {
|
||||
|
||||
memory: DomainMemoryXML {
|
||||
unit: "MB".to_string(),
|
||||
memory: self.memory,
|
||||
memory: self.memory.as_mb(),
|
||||
},
|
||||
|
||||
vcpu: DomainVCPUXML {
|
||||
@ -452,7 +452,7 @@ impl VMInfo {
|
||||
}
|
||||
},
|
||||
number_vcpu: domain.vcpu.body,
|
||||
memory: convert_size_unit_to_mb(&domain.memory.unit, domain.memory.memory)?,
|
||||
memory: FileSize::from_size_unit(&domain.memory.unit, domain.memory.memory)?,
|
||||
vnc_access: domain.devices.graphics.is_some(),
|
||||
iso_files: domain
|
||||
.devices
|
||||
|
@ -1,3 +1,12 @@
|
||||
use std::ops::Mul;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum FilesSizeUtilsError {
|
||||
#[error("UnitConvertError: {0}")]
|
||||
UnitConvert(String),
|
||||
}
|
||||
|
||||
/// Holds a data size, convertible in any form
|
||||
#[derive(
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
@ -25,6 +34,30 @@ impl FileSize {
|
||||
Self(gb * 1000 * 1000 * 1000)
|
||||
}
|
||||
|
||||
/// Convert size unit to MB
|
||||
pub fn from_size_unit(unit: &str, value: usize) -> anyhow::Result<Self> {
|
||||
let fact = match unit {
|
||||
"bytes" | "b" => 1f64,
|
||||
"KB" => 1000f64,
|
||||
"MB" => 1000f64 * 1000f64,
|
||||
"GB" => 1000f64 * 1000f64 * 1000f64,
|
||||
"TB" => 1000f64 * 1000f64 * 1000f64 * 1000f64,
|
||||
|
||||
"k" | "KiB" => 1024f64,
|
||||
"M" | "MiB" => 1024f64 * 1024f64,
|
||||
"G" | "GiB" => 1024f64 * 1024f64 * 1024f64,
|
||||
"T" | "TiB" => 1024f64 * 1024f64 * 1024f64 * 1024f64,
|
||||
|
||||
_ => {
|
||||
return Err(
|
||||
FilesSizeUtilsError::UnitConvert(format!("Unknown size unit: {unit}")).into(),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self((value as f64).mul(fact) as usize))
|
||||
}
|
||||
|
||||
/// Get file size as bytes
|
||||
pub fn as_bytes(&self) -> usize {
|
||||
self.0
|
||||
@ -35,3 +68,24 @@ impl FileSize {
|
||||
self.0 / (1000 * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::file_size_utils::FileSize;
|
||||
|
||||
#[test]
|
||||
fn convert_units_mb() {
|
||||
assert_eq!(FileSize::from_size_unit("MB", 1).unwrap().as_mb(), 1);
|
||||
assert_eq!(FileSize::from_size_unit("MB", 1000).unwrap().as_mb(), 1000);
|
||||
assert_eq!(
|
||||
FileSize::from_size_unit("GB", 1000).unwrap().as_mb(),
|
||||
1000 * 1000
|
||||
);
|
||||
assert_eq!(FileSize::from_size_unit("GB", 1).unwrap().as_mb(), 1000);
|
||||
assert_eq!(FileSize::from_size_unit("GiB", 3).unwrap().as_mb(), 3221);
|
||||
assert_eq!(
|
||||
FileSize::from_size_unit("KiB", 488281).unwrap().as_mb(),
|
||||
499
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,6 @@
|
||||
use std::ops::{Div, Mul};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum FilesUtilsError {
|
||||
#[error("UnitConvertError: {0}")]
|
||||
UnitConvert(String),
|
||||
}
|
||||
|
||||
const INVALID_CHARS: [&str; 19] = [
|
||||
"@", "\\", "/", ":", ",", "<", ">", "%", "'", "\"", "?", "{", "}", "$", "*", "|", ";", "=",
|
||||
"\t",
|
||||
@ -35,31 +28,9 @@ pub fn set_file_permission<P: AsRef<Path>>(path: P, mode: u32) -> anyhow::Result
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert size unit to MB
|
||||
pub fn convert_size_unit_to_mb(unit: &str, value: usize) -> anyhow::Result<usize> {
|
||||
let fact = match unit {
|
||||
"bytes" | "b" => 1f64,
|
||||
"KB" => 1000f64,
|
||||
"MB" => 1000f64 * 1000f64,
|
||||
"GB" => 1000f64 * 1000f64 * 1000f64,
|
||||
"TB" => 1000f64 * 1000f64 * 1000f64 * 1000f64,
|
||||
|
||||
"k" | "KiB" => 1024f64,
|
||||
"M" | "MiB" => 1024f64 * 1024f64,
|
||||
"G" | "GiB" => 1024f64 * 1024f64 * 1024f64,
|
||||
"T" | "TiB" => 1024f64 * 1024f64 * 1024f64 * 1024f64,
|
||||
|
||||
_ => {
|
||||
return Err(FilesUtilsError::UnitConvert(format!("Unknown size unit: {unit}")).into());
|
||||
}
|
||||
};
|
||||
|
||||
Ok((value as f64).mul(fact.div((1000 * 1000) as f64)).ceil() as usize)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::utils::files_utils::{check_file_name, convert_size_unit_to_mb};
|
||||
use crate::utils::files_utils::check_file_name;
|
||||
|
||||
#[test]
|
||||
fn empty_file_name() {
|
||||
@ -85,14 +56,4 @@ mod test {
|
||||
fn valid_file_name() {
|
||||
assert!(check_file_name("test.iso"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_units_mb() {
|
||||
assert_eq!(convert_size_unit_to_mb("MB", 1).unwrap(), 1);
|
||||
assert_eq!(convert_size_unit_to_mb("MB", 1000).unwrap(), 1000);
|
||||
assert_eq!(convert_size_unit_to_mb("GB", 1000).unwrap(), 1000 * 1000);
|
||||
assert_eq!(convert_size_unit_to_mb("GB", 1).unwrap(), 1000);
|
||||
assert_eq!(convert_size_unit_to_mb("GiB", 3).unwrap(), 3222);
|
||||
assert_eq!(convert_size_unit_to_mb("KiB", 488281).unwrap(), 500);
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ function VMListWidget(p: {
|
||||
{row.name}
|
||||
</TableCell>
|
||||
<TableCell>{row.description ?? ""}</TableCell>
|
||||
<TableCell>{vmMemoryToHuman(row.memory)}</TableCell>
|
||||
<TableCell>{filesize(row.memory)}</TableCell>
|
||||
<TableCell>{row.number_vcpu}</TableCell>
|
||||
<TableCell>
|
||||
<VMStatusWidget
|
||||
@ -183,13 +183,13 @@ function VMListWidget(p: {
|
||||
<TableCell></TableCell>
|
||||
<TableCell></TableCell>
|
||||
<TableCell>
|
||||
{vmMemoryToHuman(
|
||||
{filesize(
|
||||
p.list
|
||||
.filter((v) => runningVMs.has(v.name))
|
||||
.reduce((s, v) => s + v.memory, 0)
|
||||
)}
|
||||
{" / "}
|
||||
{vmMemoryToHuman(p.list.reduce((s, v) => s + v.memory, 0))}
|
||||
{filesize(p.list.reduce((s, v) => s + v.memory, 0))}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{p.list
|
||||
@ -206,7 +206,3 @@ function VMListWidget(p: {
|
||||
</TableContainer>
|
||||
);
|
||||
}
|
||||
|
||||
function vmMemoryToHuman(size: number): string {
|
||||
return filesize(size * 1000 * 1000);
|
||||
}
|
||||
|
@ -279,14 +279,16 @@ function VMDetailsTabGeneral(p: DetailsInnerProps): React.ReactElement {
|
||||
label="Memory (MB)"
|
||||
editable={p.editable}
|
||||
type="number"
|
||||
value={p.vm.memory.toString()}
|
||||
value={Math.floor(p.vm.memory / (1000 * 1000)).toString()}
|
||||
onValueChange={(v) => {
|
||||
p.vm.memory = Number(v ?? "0");
|
||||
p.vm.memory = Number(v ?? "0") * 1000 * 1000;
|
||||
p.onChange?.();
|
||||
}}
|
||||
checkValue={(v) =>
|
||||
Number(v) > ServerApi.Config.constraints.memory_size.min &&
|
||||
Number(v) < ServerApi.Config.constraints.memory_size.max
|
||||
Number(v) >
|
||||
ServerApi.Config.constraints.memory_size.min / (1000 * 1000) &&
|
||||
Number(v) <
|
||||
ServerApi.Config.constraints.memory_size.max / (1000 * 1000)
|
||||
}
|
||||
/>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user