diff --git a/Cargo.lock b/Cargo.lock index 88b9e17..5510198 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,6 +157,7 @@ dependencies = [ "rand", "reqwest", "serde", + "serde_yaml", "sha2", ] @@ -1039,6 +1040,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha2" version = "0.10.8" @@ -1265,6 +1279,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 404da3a..525f80a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ cidr = { version = "0.3.0", features = ["serde"] } rand = "0.8.5" reqwest = { version = "0.12.9", features = ["blocking"] } serde = { version = "1.0.215", features = ["derive"] } +serde_yaml = "0.9.34" sha2 = "0.10.8" diff --git a/src/config.rs b/src/config.rs index af4f9a3..89c2c43 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,30 +1,31 @@ #![allow(dead_code)] -use cidr::Ipv4Cidr; -use cidr::Ipv6Cidr; -use core::net::Ipv4Addr; -use core::net::Ipv6Addr; - +use cidr::{Ipv4Cidr, Ipv6Cidr}; +use serde::Deserialize; use std::collections::HashSet; +use std::net::{Ipv4Addr, Ipv6Addr}; use std::ops::Range; +#[derive(Deserialize, Debug)] pub struct Volume { path: String, - // maximum allowed storage in GB max_reservation: u64, } +#[derive(Deserialize, Debug)] pub struct IPv4Range { pub subnet: Ipv4Cidr, pub gateway: Ipv4Addr, pub reserved_addrs: HashSet, } +#[derive(Deserialize, Debug)] pub struct IPv6Range { pub subnet: Ipv6Cidr, pub gateway: Ipv6Addr, pub reserved_addrs: HashSet, } +#[derive(Deserialize, Debug)] pub struct Interface { pub driver: InterfaceType, pub device: String, @@ -32,19 +33,60 @@ pub struct Interface { pub ipv6: Vec, } -// TODO: create mechanic to autodetect interface type +#[derive(Deserialize, Debug)] pub enum InterfaceType { MACVTAP, IPVTAP, Bridge, } +#[derive(Deserialize, Debug)] pub struct Config { pub max_cores_per_vm: usize, pub max_vcpu_reservation: usize, pub max_mem_reservation: usize, pub network_interfaces: Vec, pub volumes: Vec, + #[serde(with = "range_format")] pub public_port_range: Range, pub max_ports_per_vm: u16, } + +mod range_format { + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use std::ops::Range; + + pub fn serialize(range: &Range, serializer: S) -> Result + where + S: Serializer, + { + let range_repr = RangeRepr { + start: range.start, + end: range.end, + }; + range_repr.serialize(serializer) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let range_repr = RangeRepr::deserialize(deserializer)?; + Ok(range_repr.start..range_repr.end) + } + + #[derive(Serialize, Deserialize)] + struct RangeRepr { + start: u16, + end: u16, + } +} + +impl Config { + pub fn from_file(path: &str) -> Result> { + let content = std::fs::read_to_string(path)?; + let config: Config = serde_yaml::from_str(&content)?; + Ok(config) + } +} + diff --git a/src/main.rs b/src/main.rs index 04751c3..b769b19 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,18 @@ mod state; mod constants; mod tcontract; -fn main() { - println!("Hello, world!"); +use crate::config::Config; + +fn main() -> Result<(), Box> { + let config = Config::from_file("test_data/config1.yaml")?; + println!("{:#?}", config); + let config = Config::from_file("test_data/config2.yaml")?; + println!("{:#?}", config); + let config = Config::from_file("test_data/config3.yaml")?; + println!("{:#?}", config); + let config = Config::from_file("test_data/config4.yaml")?; + println!("{:#?}", config); + let config = Config::from_file("test_data/config5.yaml")?; + println!("{:#?}", config); + Ok(()) } diff --git a/src/tcontract.rs b/src/tcontract.rs index a2c0bf8..bc9ddbe 100644 --- a/src/tcontract.rs +++ b/src/tcontract.rs @@ -22,3 +22,4 @@ pub struct ResourceAllocation { pub public_ipv4: Option, pub public_ipv6: Option, } + diff --git a/test_data/config1.yaml b/test_data/config1.yaml new file mode 100644 index 0000000..1c78c19 --- /dev/null +++ b/test_data/config1.yaml @@ -0,0 +1,25 @@ +max_cores_per_vm: 4 +max_vcpu_reservation: 8 +max_mem_reservation: 16384 +network_interfaces: + - driver: "MACVTAP" + device: "eth0" + ipv4: + - subnet: "192.168.1.0/24" + gateway: "192.168.1.1" + reserved_addrs: + - "192.168.1.100" + - "192.168.1.101" + ipv6: + - subnet: "2001:db8::/32" + gateway: "2001:db8::1" + reserved_addrs: + - "2001:db8::1234" + - "2001:db8::5678" +volumes: + - path: "/mnt/storage" + max_reservation: 200 +public_port_range: + start: 8000 + end: 9000 +max_ports_per_vm: 5 diff --git a/test_data/config2.yaml b/test_data/config2.yaml new file mode 100644 index 0000000..9c36395 --- /dev/null +++ b/test_data/config2.yaml @@ -0,0 +1,39 @@ +max_cores_per_vm: 16 +max_vcpu_reservation: 32 +max_mem_reservation: 65536 +network_interfaces: + - driver: "Bridge" + device: "br0" + ipv4: + - subnet: "10.0.0.0/16" + gateway: "10.0.0.1" + reserved_addrs: + - "10.0.0.100" + - "10.0.0.101" + - "10.0.0.102" + ipv6: + - subnet: "fd00::/48" + gateway: "fd00::1" + reserved_addrs: + - "fd00::1000" + - driver: "IPVTAP" + device: "tap1" + ipv4: + - subnet: "172.16.0.0/20" + gateway: "172.16.0.1" + reserved_addrs: + - "172.16.0.10" + - "172.16.0.11" + ipv6: [] +volumes: + - path: "/data/volume1" + max_reservation: 500 + - path: "/data/volume2" + max_reservation: 1000 + - path: "/backup" + max_reservation: 2000 +public_port_range: + start: 10000 + end: 11000 +max_ports_per_vm: 20 + diff --git a/test_data/config3.yaml b/test_data/config3.yaml new file mode 100644 index 0000000..dd61c56 --- /dev/null +++ b/test_data/config3.yaml @@ -0,0 +1,20 @@ +max_cores_per_vm: 12 +max_vcpu_reservation: 24 +max_mem_reservation: 49152 +network_interfaces: + - driver: "IPVTAP" + device: "tap0" + ipv4: [] + ipv6: + - subnet: "2001:db8:abcd:1234::/64" + gateway: "2001:db8:abcd:1234::1" + reserved_addrs: + - "2001:db8:abcd:1234::dead" + - "2001:db8:abcd:1234::beef" +volumes: + - path: "/ipv6/volume" + max_reservation: 600 +public_port_range: + start: 15000 + end: 16000 +max_ports_per_vm: 10 diff --git a/test_data/config4.yaml b/test_data/config4.yaml new file mode 100644 index 0000000..86beea4 --- /dev/null +++ b/test_data/config4.yaml @@ -0,0 +1,19 @@ +max_cores_per_vm: 2 +max_vcpu_reservation: 4 +max_mem_reservation: 8192 +network_interfaces: + - driver: "MACVTAP" + device: "eth0" + ipv4: + - subnet: "192.168.0.0/24" + gateway: "192.168.0.1" + reserved_addrs: [] + ipv6: [] +volumes: + - path: "/minimal/volume" + max_reservation: 100 +public_port_range: + start: 5000 + end: 5100 +max_ports_per_vm: 3 + diff --git a/test_data/config5.yaml b/test_data/config5.yaml new file mode 100644 index 0000000..23ad6dc --- /dev/null +++ b/test_data/config5.yaml @@ -0,0 +1,22 @@ +max_cores_per_vm: 8 +max_vcpu_reservation: 16 +max_mem_reservation: 32768 +network_interfaces: + - driver: "Bridge" + device: "br1" + ipv4: + - subnet: "192.168.100.0/24" + gateway: "192.168.100.1" + reserved_addrs: [] + ipv6: + - subnet: "2001:abcd::/48" + gateway: "2001:abcd::1" + reserved_addrs: [] +volumes: + - path: "/network/volume" + max_reservation: 750 +public_port_range: + start: 6000 + end: 7000 +max_ports_per_vm: 8 +