Implement a full PyO3 system to run mikrotikFindIPv6.py in-process as part of the uisp_integration run, and retrieve results. The results are then applied.

This commit is contained in:
Herbert Wolverson 2024-05-31 15:27:30 -05:00
parent bb75727940
commit a72e6ae4ff
6 changed files with 48 additions and 10 deletions

View File

@ -2,10 +2,15 @@
import routeros_api
import csv
def pullMikrotikIPv6():
def pullMikrotikIPv6(CsvPath):
import routeros_api
import csv
import json
print("Reading from " + CsvPath)
ipv4ToIPv6 = {}
routerList = []
with open('mikrotikDHCPRouterList.csv') as csv_file:
with open(CsvPath) as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
next(csv_reader)
for row in csv_reader:
@ -65,7 +70,12 @@ def pullMikrotikIPv6():
ipv4ToIPv6[ipv4] = ipv6
except:
print('Failed to find associated IPv4 for ' + ipv6)
return ipv4ToIPv6
return json.dump(ipv4ToIPv6)
def pullMikrotikIPv6_Mock(CsvPath):
return "{\n\"172.29.200.2\": \"2602:fdca:800:1500::/56\"\n}"
if __name__ == '__main__':
print(pullMikrotikIPv6())
print("Mikrotik IPv6 Finder")
#print(pullMikrotikIPv6())

View File

@ -19,3 +19,4 @@ csv = "1.3.0"
serde_json = "1.0.116"
ip_network_table = "0"
ip_network = "0"
pyo3 = "0.20"

View File

@ -58,6 +58,7 @@ pub async fn build_flat_network(
// Simple Shaped Devices File
let mut shaped_devices = Vec::new();
let ipv4_to_v6 = Vec::new();
for site in sites.iter() {
if let Some(site_id) = &site.identification {
if let Some(site_type) = &site_id.site_type {
@ -73,7 +74,7 @@ pub async fn build_flat_network(
* config.uisp_integration.commit_bandwidth_multiplier)
as u64;
for device in devices.iter() {
let dev = UispDevice::from_uisp(device, &config, &ip_ranges);
let dev = UispDevice::from_uisp(device, &config, &ip_ranges, &ipv4_to_v6);
if dev.site_id == site.id {
// We're an endpoint in the right sight. We're getting there
let sd = ShapedDevice {

View File

@ -11,6 +11,7 @@ mod tree_walk;
mod uisp_fetch;
mod utils;
mod zero_capacity_sites;
mod mikrotik;
use crate::errors::UispIntegrationError;
use crate::ip_ranges::IpRanges;
@ -55,12 +56,19 @@ pub async fn build_full_network(
// Obtain the UISP data and transform it into easier to work with types
let (sites_raw, devices_raw, data_links_raw) = load_uisp_data(config.clone()).await?;
// If Mikrotik is enabled, we need to fetch the Mikrotik data
let ipv4_to_v6 = mikrotik::mikrotik_data(&config).await.unwrap_or_else(|_| Vec::new());
//println!("{:?}", ipv4_to_v6);
// Parse the UISP data into a more usable format
let (mut sites, data_links, devices) = parse_uisp_datasets(
&sites_raw,
&data_links_raw,
&devices_raw,
&config,
&ip_ranges,
ipv4_to_v6
);
// Check root sites

View File

@ -1,5 +1,5 @@
use crate::ip_ranges::IpRanges;
use crate::uisp_types::{UispDataLink, UispDevice, UispSite};
use crate::uisp_types::{Ipv4ToIpv6, UispDataLink, UispDevice, UispSite};
use lqos_config::Config;
use tracing::info;
use uisp::{DataLink, Device, Site};
@ -21,11 +21,12 @@ pub fn parse_uisp_datasets(
devices_raw: &[Device],
config: &Config,
ip_ranges: &IpRanges,
ipv4_to_v6: Vec<Ipv4ToIpv6>,
) -> (Vec<UispSite>, Vec<UispDataLink>, Vec<UispDevice>) {
let (mut sites, data_links, devices) = (
parse_sites(sites_raw, config),
parse_data_links(data_links_raw),
parse_devices(devices_raw, config, ip_ranges),
parse_devices(devices_raw, config, ip_ranges, ipv4_to_v6),
);
// Assign devices to sites
@ -63,10 +64,10 @@ fn parse_data_links(data_links_raw: &[DataLink]) -> Vec<UispDataLink> {
data_links
}
fn parse_devices(devices_raw: &[Device], config: &Config, ip_ranges: &IpRanges) -> Vec<UispDevice> {
fn parse_devices(devices_raw: &[Device], config: &Config, ip_ranges: &IpRanges, ipv4_to_v6: Vec<Ipv4ToIpv6>) -> Vec<UispDevice> {
let devices: Vec<UispDevice> = devices_raw
.iter()
.map(|d| UispDevice::from_uisp(d, config, ip_ranges))
.map(|d| UispDevice::from_uisp(d, config, ip_ranges, &ipv4_to_v6))
.collect();
info!("{} devices have been sucessfully parsed", devices.len());
devices

View File

@ -4,6 +4,13 @@ use std::collections::HashSet;
use std::net::IpAddr;
use uisp::Device;
#[derive(Debug)]
pub struct Ipv4ToIpv6 {
pub ipv4: String,
pub ipv6: String,
}
/// Trimmed UISP device for easy use
pub struct UispDevice {
pub id: String,
@ -23,7 +30,7 @@ impl UispDevice {
/// * `device` - The device to convert
/// * `config` - The configuration
/// * `ip_ranges` - The IP ranges to use for the network
pub fn from_uisp(device: &Device, config: &Config, ip_ranges: &IpRanges) -> Self {
pub fn from_uisp(device: &Device, config: &Config, ip_ranges: &IpRanges, ipv4_to_v6: &[Ipv4ToIpv6]) -> Self {
let mut ipv4 = HashSet::new();
let mut ipv6 = HashSet::new();
let mac = if let Some(id) = &device.identification.mac {
@ -58,8 +65,18 @@ impl UispDevice {
if address.contains('/') {
let splits: Vec<_> = address.split('/').collect();
ipv4.insert(format!("{}/32", splits[0]));
// Check for a Mikrotik Mapping
if let Some(mapping) = ipv4_to_v6.iter().find(|m| m.ipv4 == splits[0]) {
ipv6.insert(mapping.ipv6.clone());
}
} else {
ipv4.insert(format!("{address}/32"));
// Check for a Mikrotik Mapping
if let Some(mapping) = ipv4_to_v6.iter().find(|m| m.ipv4 == address.as_str()) {
ipv6.insert(mapping.ipv6.clone());
}
}
}
}