feat: assign mac / gateway

This commit is contained in:
2024-11-29 11:18:02 +00:00
parent 1cc4d40082
commit 06d8339653
14 changed files with 238 additions and 16 deletions

View File

@ -1,4 +1,5 @@
use anyhow::Error;
use clap::Parser;
use config::{Config, File};
use fedimint_tonic_lnd::connect;
use lnvps::api;
@ -14,12 +15,20 @@ use log::error;
use std::net::{IpAddr, SocketAddr};
use std::time::Duration;
#[derive(Parser)]
#[clap(about, version, author)]
struct Args {
#[clap(short, long)]
config: Option<String>,
}
#[rocket::main]
async fn main() -> Result<(), Error> {
pretty_env_logger::init();
let args = Args::parse();
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()?
.try_deserialize()?;

View File

@ -8,3 +8,4 @@ pub mod provisioner;
pub mod settings;
pub mod status;
pub mod worker;
pub mod router;

View File

@ -17,6 +17,8 @@ use lnvps_db::{
VmPayment,
};
use log::{error, info, warn};
use nostr::util::hex;
use rand::random;
use rand::seq::IteratorRandom;
use reqwest::Url;
use std::collections::HashSet;
@ -82,17 +84,22 @@ impl Provisioner for LNVpsProvisioner {
for image in self.db.list_os_image().await? {
info!("Downloading image {} on {}", image.url, host.name);
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");
continue;
}
let t_download = client.download_image(DownloadUrlRequest {
content: StorageContent::ISO,
node: host.name.clone(),
storage: iso_storage.clone(),
url: image.url.clone(),
filename: i_name,
}).await?;
let t_download = client
.download_image(DownloadUrlRequest {
content: StorageContent::ISO,
node: host.name.clone(),
storage: iso_storage.clone(),
url: image.url.clone(),
filename: i_name,
})
.await?;
client.wait_for_task(&t_download).await?;
}
}
@ -137,6 +144,12 @@ impl Provisioner for LNVpsProvisioner {
memory: template.memory,
disk_size: template.disk_size,
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()
};
@ -254,6 +267,7 @@ impl Provisioner for LNVpsProvisioner {
vm_id,
ip_range_id: range.id,
ip: IpNetwork::new(ip, range_cidr.prefix())?.to_string(),
..Default::default()
};
let id = self.db.insert_vm_ip_assignment(&assignment).await?;
assignment.id = id;
@ -280,12 +294,23 @@ impl Provisioner for LNVpsProvisioner {
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
.iter()
.map_while(|ip| {
if let Ok(net) = ip.ip.parse::<IpNetwork>() {
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),
})
} else {
@ -305,7 +330,7 @@ impl Provisioner for LNVpsProvisioner {
let ssh_key = self.db.get_user_ssh_key(vm.ssh_key_id).await?;
let mut net = vec![
"virtio".to_string(),
format!("virtio={}", vm.mac_address),
format!("bridge={}", self.config.bridge),
];
if let Some(t) = self.config.vlan {

25
src/router/mikrotik.rs Normal file
View 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
View 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::*;