feat: assign mac / gateway
This commit is contained in:
parent
1cc4d40082
commit
06d8339653
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
**/target
|
**/target
|
||||||
.idea/
|
.idea/
|
||||||
|
*.config.yaml
|
108
Cargo.lock
generated
108
Cargo.lock
generated
@ -69,6 +69,55 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.91"
|
version = "1.0.91"
|
||||||
@ -474,6 +523,52 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@ -1695,6 +1790,12 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -1781,6 +1882,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"clap",
|
||||||
"config",
|
"config",
|
||||||
"fedimint-tonic-lnd",
|
"fedimint-tonic-lnd",
|
||||||
"ipnetwork",
|
"ipnetwork",
|
||||||
@ -4098,6 +4200,12 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -25,3 +25,4 @@ urlencoding = "2.1.3"
|
|||||||
fedimint-tonic-lnd = { version = "0.2.0", default-features = false, features = ["invoicesrpc"] }
|
fedimint-tonic-lnd = { version = "0.2.0", default-features = false, features = ["invoicesrpc"] }
|
||||||
ipnetwork = "0.20.0"
|
ipnetwork = "0.20.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
clap = { version = "4.5.21", features = ["derive"] }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# MySQL database connection string
|
|
||||||
db: "mysql://root:root@localhost:3376/lnvps"
|
db: "mysql://root:root@localhost:3376/lnvps"
|
||||||
lnd:
|
lnd:
|
||||||
url: "https://127.0.0.1:10003"
|
url: "https://127.0.0.1:10003"
|
||||||
|
4
lnvps_db/migrations/20241127163556_networking.sql
Normal file
4
lnvps_db/migrations/20241127163556_networking.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
alter table ip_range
|
||||||
|
add column gateway varchar(255) not null;
|
||||||
|
alter table vm
|
||||||
|
add column mac_address varchar(20) not null;
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{LNVpsDb, Vm, VmTemplate};
|
use crate::{LNVpsDb, Vm, VmIpAssignment, VmTemplate};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@ -49,3 +49,15 @@ impl<D: Deref<Target = dyn LNVpsDb> + Sync> Hydrate<D> for VmTemplate {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<D: Deref<Target = dyn LNVpsDb> + Sync> Hydrate<D> for VmIpAssignment {
|
||||||
|
async fn hydrate_up(&mut self, db: &D) -> Result<()> {
|
||||||
|
self.ip_range = Some(db.get_ip_range(self.ip_range_id).await?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn hydrate_down(&mut self, db: &D) -> Result<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -60,6 +60,9 @@ pub trait LNVpsDb: Sync + Send {
|
|||||||
/// List available OS images
|
/// List available OS images
|
||||||
async fn list_os_image(&self) -> Result<Vec<VmOsImage>>;
|
async fn list_os_image(&self) -> Result<Vec<VmOsImage>>;
|
||||||
|
|
||||||
|
/// List available IP Ranges
|
||||||
|
async fn get_ip_range(&self, id: u64) -> Result<IpRange>;
|
||||||
|
|
||||||
/// List available IP Ranges
|
/// List available IP Ranges
|
||||||
async fn list_ip_range(&self) -> Result<Vec<IpRange>>;
|
async fn list_ip_range(&self) -> Result<Vec<IpRange>>;
|
||||||
|
|
||||||
|
@ -149,6 +149,7 @@ impl VmOsImage {
|
|||||||
pub struct IpRange {
|
pub struct IpRange {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
pub cidr: String,
|
pub cidr: String,
|
||||||
|
pub gateway: String,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub region_id: u64,
|
pub region_id: u64,
|
||||||
}
|
}
|
||||||
@ -225,6 +226,8 @@ pub struct Vm {
|
|||||||
pub disk_size: u64,
|
pub disk_size: u64,
|
||||||
/// The [VmHostDisk] this VM is on
|
/// The [VmHostDisk] this VM is on
|
||||||
pub disk_id: u64,
|
pub disk_id: u64,
|
||||||
|
/// Network MAC address
|
||||||
|
pub mac_address: String,
|
||||||
|
|
||||||
#[sqlx(skip)]
|
#[sqlx(skip)]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@ -244,12 +247,16 @@ pub struct Vm {
|
|||||||
pub ip_assignments: Option<Vec<VmIpAssignment>>,
|
pub ip_assignments: Option<Vec<VmIpAssignment>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, FromRow, Clone, Debug)]
|
#[derive(Serialize, Deserialize, FromRow, Clone, Debug, Default)]
|
||||||
pub struct VmIpAssignment {
|
pub struct VmIpAssignment {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
pub vm_id: u64,
|
pub vm_id: u64,
|
||||||
pub ip_range_id: u64,
|
pub ip_range_id: u64,
|
||||||
pub ip: String,
|
pub ip: String,
|
||||||
|
|
||||||
|
#[sqlx(skip)]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub ip_range: Option<IpRange>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
|
@ -152,6 +152,14 @@ impl LNVpsDb for LNVpsDbMysql {
|
|||||||
.map_err(Error::new)
|
.map_err(Error::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_ip_range(&self, id: u64) -> Result<IpRange> {
|
||||||
|
sqlx::query_as("select * from ip_range where id=?")
|
||||||
|
.bind(id)
|
||||||
|
.fetch_one(&self.db)
|
||||||
|
.await
|
||||||
|
.map_err(Error::new)
|
||||||
|
}
|
||||||
|
|
||||||
async fn list_ip_range(&self) -> Result<Vec<IpRange>> {
|
async fn list_ip_range(&self) -> Result<Vec<IpRange>> {
|
||||||
sqlx::query_as("select * from ip_range")
|
sqlx::query_as("select * from ip_range")
|
||||||
.fetch_all(&self.db)
|
.fetch_all(&self.db)
|
||||||
@ -206,7 +214,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn insert_vm(&self, vm: &Vm) -> Result<u64> {
|
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,cpu,memory,disk_size,disk_id) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) returning id")
|
Ok(sqlx::query("insert into vm(host_id,user_id,image_id,template_id,ssh_key_id,created,expires,cpu,memory,disk_size,disk_id,mac_address) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) returning id")
|
||||||
.bind(vm.host_id)
|
.bind(vm.host_id)
|
||||||
.bind(vm.user_id)
|
.bind(vm.user_id)
|
||||||
.bind(vm.image_id)
|
.bind(vm.image_id)
|
||||||
@ -218,6 +226,7 @@ impl LNVpsDb for LNVpsDbMysql {
|
|||||||
.bind(vm.memory)
|
.bind(vm.memory)
|
||||||
.bind(vm.disk_size)
|
.bind(vm.disk_size)
|
||||||
.bind(vm.disk_id)
|
.bind(vm.disk_id)
|
||||||
|
.bind(&vm.mac_address)
|
||||||
.fetch_one(&self.db)
|
.fetch_one(&self.db)
|
||||||
.await
|
.await
|
||||||
.map_err(Error::new)?
|
.map_err(Error::new)?
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use clap::Parser;
|
||||||
use config::{Config, File};
|
use config::{Config, File};
|
||||||
use fedimint_tonic_lnd::connect;
|
use fedimint_tonic_lnd::connect;
|
||||||
use lnvps::api;
|
use lnvps::api;
|
||||||
@ -14,12 +15,20 @@ use log::error;
|
|||||||
use std::net::{IpAddr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[clap(about, version, author)]
|
||||||
|
struct Args {
|
||||||
|
#[clap(short, long)]
|
||||||
|
config: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[rocket::main]
|
#[rocket::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), Error> {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
|
let args = Args::parse();
|
||||||
let settings: Settings = Config::builder()
|
let settings: Settings = Config::builder()
|
||||||
.add_source(File::with_name("config.yaml"))
|
.add_source(File::with_name(&args.config.unwrap_or("config.yaml".to_string())))
|
||||||
.build()?
|
.build()?
|
||||||
.try_deserialize()?;
|
.try_deserialize()?;
|
||||||
|
|
||||||
|
@ -8,3 +8,4 @@ pub mod provisioner;
|
|||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
pub mod worker;
|
pub mod worker;
|
||||||
|
pub mod router;
|
||||||
|
@ -17,6 +17,8 @@ use lnvps_db::{
|
|||||||
VmPayment,
|
VmPayment,
|
||||||
};
|
};
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
|
use nostr::util::hex;
|
||||||
|
use rand::random;
|
||||||
use rand::seq::IteratorRandom;
|
use rand::seq::IteratorRandom;
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@ -82,17 +84,22 @@ impl Provisioner for LNVpsProvisioner {
|
|||||||
for image in self.db.list_os_image().await? {
|
for image in self.db.list_os_image().await? {
|
||||||
info!("Downloading image {} on {}", image.url, host.name);
|
info!("Downloading image {} on {}", image.url, host.name);
|
||||||
let i_name = image.filename()?;
|
let i_name = image.filename()?;
|
||||||
if files.iter().any(|v| v.vol_id.ends_with(&format!("iso/{i_name}"))) {
|
if files
|
||||||
|
.iter()
|
||||||
|
.any(|v| v.vol_id.ends_with(&format!("iso/{i_name}")))
|
||||||
|
{
|
||||||
info!("Already downloaded, skipping");
|
info!("Already downloaded, skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let t_download = client.download_image(DownloadUrlRequest {
|
let t_download = client
|
||||||
content: StorageContent::ISO,
|
.download_image(DownloadUrlRequest {
|
||||||
node: host.name.clone(),
|
content: StorageContent::ISO,
|
||||||
storage: iso_storage.clone(),
|
node: host.name.clone(),
|
||||||
url: image.url.clone(),
|
storage: iso_storage.clone(),
|
||||||
filename: i_name,
|
url: image.url.clone(),
|
||||||
}).await?;
|
filename: i_name,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
client.wait_for_task(&t_download).await?;
|
client.wait_for_task(&t_download).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,6 +144,12 @@ impl Provisioner for LNVpsProvisioner {
|
|||||||
memory: template.memory,
|
memory: template.memory,
|
||||||
disk_size: template.disk_size,
|
disk_size: template.disk_size,
|
||||||
disk_id: pick_disk.id,
|
disk_id: pick_disk.id,
|
||||||
|
mac_address: format!(
|
||||||
|
"bc:24:11:{}:{}:{}",
|
||||||
|
hex::encode(&[random::<u8>()]),
|
||||||
|
hex::encode(&[random::<u8>()]),
|
||||||
|
hex::encode(&[random::<u8>()])
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -254,6 +267,7 @@ impl Provisioner for LNVpsProvisioner {
|
|||||||
vm_id,
|
vm_id,
|
||||||
ip_range_id: range.id,
|
ip_range_id: range.id,
|
||||||
ip: IpNetwork::new(ip, range_cidr.prefix())?.to_string(),
|
ip: IpNetwork::new(ip, range_cidr.prefix())?.to_string(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let id = self.db.insert_vm_ip_assignment(&assignment).await?;
|
let id = self.db.insert_vm_ip_assignment(&assignment).await?;
|
||||||
assignment.id = id;
|
assignment.id = id;
|
||||||
@ -280,12 +294,23 @@ impl Provisioner for LNVpsProvisioner {
|
|||||||
ips = self.allocate_ips(vm.id).await?;
|
ips = self.allocate_ips(vm.id).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load ranges
|
||||||
|
for ip in &mut ips {
|
||||||
|
ip.hydrate_up(&self.db).await?;
|
||||||
|
}
|
||||||
|
|
||||||
let mut ip_config = ips
|
let mut ip_config = ips
|
||||||
.iter()
|
.iter()
|
||||||
.map_while(|ip| {
|
.map_while(|ip| {
|
||||||
if let Ok(net) = ip.ip.parse::<IpNetwork>() {
|
if let Ok(net) = ip.ip.parse::<IpNetwork>() {
|
||||||
Some(match net {
|
Some(match net {
|
||||||
IpNetwork::V4(addr) => format!("ip={}", addr),
|
IpNetwork::V4(addr) => {
|
||||||
|
format!(
|
||||||
|
"ip={},gw={}",
|
||||||
|
addr,
|
||||||
|
ip.ip_range.as_ref().map(|r| &r.gateway).unwrap()
|
||||||
|
)
|
||||||
|
}
|
||||||
IpNetwork::V6(addr) => format!("ip6={}", addr),
|
IpNetwork::V6(addr) => format!("ip6={}", addr),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -305,7 +330,7 @@ impl Provisioner for LNVpsProvisioner {
|
|||||||
let ssh_key = self.db.get_user_ssh_key(vm.ssh_key_id).await?;
|
let ssh_key = self.db.get_user_ssh_key(vm.ssh_key_id).await?;
|
||||||
|
|
||||||
let mut net = vec![
|
let mut net = vec![
|
||||||
"virtio".to_string(),
|
format!("virtio={}", vm.mac_address),
|
||||||
format!("bridge={}", self.config.bridge),
|
format!("bridge={}", self.config.bridge),
|
||||||
];
|
];
|
||||||
if let Some(t) = self.config.vlan {
|
if let Some(t) = self.config.vlan {
|
||||||
|
25
src/router/mikrotik.rs
Normal file
25
src/router/mikrotik.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use std::net::IpAddr;
|
||||||
|
use lnvps_db::VmIpAssignment;
|
||||||
|
use rocket::async_trait;
|
||||||
|
use crate::router::Router;
|
||||||
|
|
||||||
|
pub struct MikrotikRouter {
|
||||||
|
url: String,
|
||||||
|
token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MikrotikRouter {
|
||||||
|
pub fn new(url: &str, token: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
url: url.to_string(),
|
||||||
|
token: token.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Router for MikrotikRouter {
|
||||||
|
async fn add_arp_entry(&self, ip: IpAddr, mac: &[u8; 6], comment: Option<&str>) -> anyhow::Result<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
18
src/router/mod.rs
Normal file
18
src/router/mod.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use rocket::async_trait;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
|
||||||
|
/// Router defines a network device used to access the hosts
|
||||||
|
///
|
||||||
|
/// In our infrastructure we use this to add static ARP entries on the router
|
||||||
|
/// for every IP assignment, this way we don't need to have a ton of ARP requests on the
|
||||||
|
/// VM network because of people doing IP scanning
|
||||||
|
///
|
||||||
|
/// It also prevents people from re-assigning their IP to another in the range,
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Router {
|
||||||
|
async fn add_arp_entry(&self, ip: IpAddr, mac: &[u8; 6], comment: Option<&str>) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod mikrotik;
|
||||||
|
pub use mikrotik::*;
|
Loading…
x
Reference in New Issue
Block a user