feat: assign mac / gateway
This commit is contained in:
@ -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()?;
|
||||
|
||||
|
@ -8,3 +8,4 @@ pub mod provisioner;
|
||||
pub mod settings;
|
||||
pub mod status;
|
||||
pub mod worker;
|
||||
pub mod router;
|
||||
|
@ -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
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::*;
|
Reference in New Issue
Block a user