feat: fill in ipv6 addresses
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:
@ -57,9 +57,6 @@ async fn main() -> Result<(), Error> {
|
||||
}
|
||||
let db: Arc<dyn LNVpsDb> = Arc::new(db);
|
||||
|
||||
// run data migrations
|
||||
run_data_migrations(db.clone(), &settings).await?;
|
||||
|
||||
let nostr_client = if let Some(ref c) = settings.nostr {
|
||||
let cx = Client::builder().signer(Keys::parse(&c.nsec)?).build();
|
||||
for r in &c.relays {
|
||||
@ -78,6 +75,9 @@ async fn main() -> Result<(), Error> {
|
||||
let provisioner = settings.get_provisioner(db.clone(), node.clone(), exchange.clone());
|
||||
provisioner.init().await?;
|
||||
|
||||
// run data migrations
|
||||
run_data_migrations(db.clone(), provisioner.clone(), &settings).await?;
|
||||
|
||||
let mut worker = Worker::new(
|
||||
db.clone(),
|
||||
provisioner.clone(),
|
||||
|
49
src/data_migration/ip6_init.rs
Normal file
49
src/data_migration/ip6_init.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::data_migration::DataMigration;
|
||||
use crate::provisioner::{LNVpsProvisioner, NetworkProvisioner};
|
||||
use ipnetwork::IpNetwork;
|
||||
use lnvps_db::LNVpsDb;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use log::info;
|
||||
|
||||
pub struct Ip6InitDataMigration {
|
||||
db: Arc<dyn LNVpsDb>,
|
||||
provisioner: Arc<LNVpsProvisioner>,
|
||||
}
|
||||
|
||||
impl Ip6InitDataMigration {
|
||||
pub fn new(db: Arc<dyn LNVpsDb>, provisioner: Arc<LNVpsProvisioner>) -> Ip6InitDataMigration {
|
||||
Self { db, provisioner }
|
||||
}
|
||||
}
|
||||
|
||||
impl DataMigration for Ip6InitDataMigration {
|
||||
fn migrate(&self) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> {
|
||||
let db = self.db.clone();
|
||||
let provisioner = self.provisioner.clone();
|
||||
Box::pin(async move {
|
||||
let net = NetworkProvisioner::new(db.clone());
|
||||
let vms = db.list_vms().await?;
|
||||
for vm in vms {
|
||||
let host = db.get_host(vm.host_id).await?;
|
||||
let ips = db.list_vm_ip_assignments(vm.id).await?;
|
||||
// if no ipv6 address is picked already pick one
|
||||
if ips.iter().all(|i| {
|
||||
IpNetwork::from_str(&i.ip)
|
||||
.map(|i| i.is_ipv4())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
{
|
||||
let ips_pick = net.pick_ip_for_region(host.region_id).await?;
|
||||
if let Some(mut v6) = ips_pick.ip6 {
|
||||
info!("Assigning ip {} to vm {}", v6.ip, vm.id);
|
||||
provisioner.assign_available_v6_to_vm(&vm, &mut v6).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
@ -6,18 +6,23 @@ use log::{error, info};
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use crate::data_migration::ip6_init::Ip6InitDataMigration;
|
||||
use crate::provisioner::LNVpsProvisioner;
|
||||
|
||||
mod dns;
|
||||
mod ip6_init;
|
||||
|
||||
/// Basic data migration to run at startup
|
||||
pub trait DataMigration: Send + Sync {
|
||||
fn migrate(&self) -> Pin<Box<dyn Future<Output = Result<()>> + Send>>;
|
||||
}
|
||||
|
||||
pub async fn run_data_migrations(db: Arc<dyn LNVpsDb>, settings: &Settings) -> Result<()> {
|
||||
let mut migrations: Vec<Arc<dyn DataMigration>> = vec![];
|
||||
pub async fn run_data_migrations(db: Arc<dyn LNVpsDb>, lnvps: Arc<LNVpsProvisioner>, settings: &Settings) -> Result<()> {
|
||||
let mut migrations: Vec<Box<dyn DataMigration>> = vec![];
|
||||
migrations.push(Box::new(Ip6InitDataMigration::new(db.clone(), lnvps.clone())));
|
||||
|
||||
if let Some(d) = DnsDataMigration::new(db.clone(), settings) {
|
||||
migrations.push(Arc::new(d));
|
||||
migrations.push(Box::new(d));
|
||||
}
|
||||
|
||||
info!("Running {} data migrations", migrations.len());
|
||||
|
@ -3,7 +3,9 @@ use crate::exchange::{Currency, CurrencyAmount, ExchangeRateService};
|
||||
use crate::fiat::FiatPaymentService;
|
||||
use crate::host::{get_host_client, FullVmInfo};
|
||||
use crate::lightning::{AddInvoiceRequest, LightningNode};
|
||||
use crate::provisioner::{CostResult, HostCapacityService, NetworkProvisioner, PricingEngine};
|
||||
use crate::provisioner::{
|
||||
AvailableIp, CostResult, HostCapacityService, NetworkProvisioner, PricingEngine,
|
||||
};
|
||||
use crate::router::{ArpEntry, MikrotikRouter, OvhDedicatedServerVMacRouter, Router};
|
||||
use crate::settings::{ProvisionerConfig, Settings};
|
||||
use anyhow::{bail, ensure, Context, Result};
|
||||
@ -284,6 +286,47 @@ impl LNVpsProvisioner {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn assign_available_v4_to_vm(
|
||||
&self,
|
||||
vm: &Vm,
|
||||
v4: &AvailableIp,
|
||||
) -> Result<VmIpAssignment> {
|
||||
let mut assignment = VmIpAssignment {
|
||||
vm_id: vm.id,
|
||||
ip_range_id: v4.range_id,
|
||||
ip: v4.ip.ip().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.save_ip_assignment(&mut assignment).await?;
|
||||
Ok(assignment)
|
||||
}
|
||||
|
||||
pub async fn assign_available_v6_to_vm(
|
||||
&self,
|
||||
vm: &Vm,
|
||||
v6: &mut AvailableIp,
|
||||
) -> Result<VmIpAssignment> {
|
||||
match v6.mode {
|
||||
// it's a bit awkward, but we need to update the IP AFTER its been picked
|
||||
// simply because sometimes we don't know the MAC of the NIC yet
|
||||
IpRangeAllocationMode::SlaacEui64 => {
|
||||
let mac = NetworkProvisioner::parse_mac(&vm.mac_address)?;
|
||||
let addr = NetworkProvisioner::calculate_eui64(&mac, &v6.ip)?;
|
||||
v6.ip = IpNetwork::new(addr, v6.ip.prefix())?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let mut assignment = VmIpAssignment {
|
||||
vm_id: vm.id,
|
||||
ip_range_id: v6.range_id,
|
||||
ip: v6.ip.ip().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
self.save_ip_assignment(&mut assignment).await?;
|
||||
Ok(assignment)
|
||||
}
|
||||
|
||||
async fn allocate_ips(&self, vm_id: u64) -> Result<Vec<VmIpAssignment>> {
|
||||
let mut vm = self.db.get_vm(vm_id).await?;
|
||||
let existing_ips = self.db.list_vm_ip_assignments(vm_id).await?;
|
||||
@ -299,12 +342,7 @@ impl LNVpsProvisioner {
|
||||
let mut assignments = vec![];
|
||||
match ip.ip4 {
|
||||
Some(v4) => {
|
||||
let mut assignment = VmIpAssignment {
|
||||
vm_id,
|
||||
ip_range_id: v4.range_id,
|
||||
ip: v4.ip.ip().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut assignment = self.assign_available_v4_to_vm(&vm, &v4).await?;
|
||||
|
||||
//generate mac address from ip assignment
|
||||
let mac = self.get_mac_for_assignment(&host, &vm, &assignment).await?;
|
||||
@ -312,33 +350,13 @@ impl LNVpsProvisioner {
|
||||
assignment.arp_ref = mac.id; // store ref if we got one
|
||||
self.db.update_vm(&vm).await?;
|
||||
|
||||
self.save_ip_assignment(&mut assignment).await?;
|
||||
assignments.push(assignment);
|
||||
}
|
||||
/// TODO: add expected number of IPS per templates
|
||||
None => bail!("Cannot provision VM without an IPv4 address"),
|
||||
}
|
||||
match ip.ip6 {
|
||||
Some(mut v6) => {
|
||||
match v6.mode {
|
||||
// it's a bit awkward but we need to update the IP AFTER its been picked
|
||||
// simply because sometimes we dont know the MAC of the NIC yet
|
||||
IpRangeAllocationMode::SlaacEui64 => {
|
||||
let mac = NetworkProvisioner::parse_mac(&vm.mac_address)?;
|
||||
let addr = NetworkProvisioner::calculate_eui64(&mac, &v6.ip)?;
|
||||
v6.ip = IpNetwork::new(addr, v6.ip.prefix())?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let mut assignment = VmIpAssignment {
|
||||
vm_id,
|
||||
ip_range_id: v6.range_id,
|
||||
ip: v6.ip.ip().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
self.save_ip_assignment(&mut assignment).await?;
|
||||
assignments.push(assignment);
|
||||
}
|
||||
None => {}
|
||||
if let Some(mut v6) = ip.ip6 {
|
||||
assignments.push(self.assign_available_v6_to_vm(&vm, &mut v6).await?);
|
||||
}
|
||||
|
||||
Ok(assignments)
|
||||
|
Reference in New Issue
Block a user