Add basic NAT structures
This commit is contained in:
		@@ -7,6 +7,7 @@ use crate::libvirt_rest_structures::hypervisor::*;
 | 
				
			|||||||
use crate::libvirt_rest_structures::net::*;
 | 
					use crate::libvirt_rest_structures::net::*;
 | 
				
			||||||
use crate::libvirt_rest_structures::nw_filter::{NetworkFilter, NetworkFilterName};
 | 
					use crate::libvirt_rest_structures::nw_filter::{NetworkFilter, NetworkFilterName};
 | 
				
			||||||
use crate::libvirt_rest_structures::vm::*;
 | 
					use crate::libvirt_rest_structures::vm::*;
 | 
				
			||||||
 | 
					use crate::nat::nat_lib;
 | 
				
			||||||
use actix::{Actor, Context, Handler, Message};
 | 
					use actix::{Actor, Context, Handler, Message};
 | 
				
			||||||
use image::ImageOutputFormat;
 | 
					use image::ImageOutputFormat;
 | 
				
			||||||
use std::io::Cursor;
 | 
					use std::io::Cursor;
 | 
				
			||||||
@@ -395,6 +396,9 @@ impl Handler<DefineNetwork> for LibVirtActor {
 | 
				
			|||||||
        let network = Network::define_xml(&self.m, &network_xml)?;
 | 
					        let network = Network::define_xml(&self.m, &network_xml)?;
 | 
				
			||||||
        let uuid = XMLUuid::parse_from_str(&network.get_uuid_string()?)?;
 | 
					        let uuid = XMLUuid::parse_from_str(&network.get_uuid_string()?)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Save NAT definition
 | 
				
			||||||
 | 
					        nat_lib::save_nat_def(&msg.0)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Save a copy of the source definition
 | 
					        // Save a copy of the source definition
 | 
				
			||||||
        msg.0.uuid = Some(uuid);
 | 
					        msg.0.uuid = Some(uuid);
 | 
				
			||||||
        let json = serde_json::to_string(&msg.0)?;
 | 
					        let json = serde_json::to_string(&msg.0)?;
 | 
				
			||||||
@@ -464,9 +468,12 @@ impl Handler<DeleteNetwork> for LibVirtActor {
 | 
				
			|||||||
    fn handle(&mut self, msg: DeleteNetwork, _ctx: &mut Self::Context) -> Self::Result {
 | 
					    fn handle(&mut self, msg: DeleteNetwork, _ctx: &mut Self::Context) -> Self::Result {
 | 
				
			||||||
        log::debug!("Delete network: {}\n", msg.0.as_string());
 | 
					        log::debug!("Delete network: {}\n", msg.0.as_string());
 | 
				
			||||||
        let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
 | 
					        let network = Network::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
 | 
				
			||||||
        let network_name = network.get_name()?;
 | 
					        let network_name = NetworkName(network.get_name()?);
 | 
				
			||||||
        network.undefine()?;
 | 
					        network.undefine()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Remove NAT definition, if any
 | 
				
			||||||
 | 
					        nat_lib::remove_nat_def(&network_name)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Remove backup definition
 | 
					        // Remove backup definition
 | 
				
			||||||
        let backup_definition = AppConfig::get().net_definition_path(&network_name);
 | 
					        let backup_definition = AppConfig::get().net_definition_path(&network_name);
 | 
				
			||||||
        if backup_definition.exists() {
 | 
					        if backup_definition.exists() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
 | 
					use crate::constants;
 | 
				
			||||||
use crate::libvirt_lib_structures::XMLUuid;
 | 
					use crate::libvirt_lib_structures::XMLUuid;
 | 
				
			||||||
 | 
					use crate::libvirt_rest_structures::net::NetworkName;
 | 
				
			||||||
use crate::libvirt_rest_structures::nw_filter::NetworkFilterName;
 | 
					use crate::libvirt_rest_structures::nw_filter::NetworkFilterName;
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use std::net::IpAddr;
 | 
					use std::net::IpAddr;
 | 
				
			||||||
@@ -250,8 +252,16 @@ impl AppConfig {
 | 
				
			|||||||
        self.definitions_path().join(format!("vm-{name}.json"))
 | 
					        self.definitions_path().join(format!("vm-{name}.json"))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn net_definition_path(&self, name: &str) -> PathBuf {
 | 
					    pub fn net_definition_path(&self, name: &NetworkName) -> PathBuf {
 | 
				
			||||||
        self.definitions_path().join(format!("net-{name}.json"))
 | 
					        self.definitions_path().join(format!("net-{}.json", name.0))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn nat_path(&self) -> PathBuf {
 | 
				
			||||||
 | 
					        self.storage_path().join(constants::STORAGE_NAT_DIR)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn net_nat_path(&self, name: &NetworkName) -> PathBuf {
 | 
				
			||||||
 | 
					        self.nat_path().join(format!("nat-{}.json", name.0))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn net_filter_definition_path(&self, name: &NetworkFilterName) -> PathBuf {
 | 
					    pub fn net_filter_definition_path(&self, name: &NetworkFilterName) -> PathBuf {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,3 +77,6 @@ pub const BUILTIN_NETWORK_FILTER_RULES: [&str; 24] = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// List of valid network chains
 | 
					/// List of valid network chains
 | 
				
			||||||
pub const NETWORK_CHAINS: [&str; 8] = ["root", "mac", "stp", "vlan", "arp", "rarp", "ipv4", "ipv6"];
 | 
					pub const NETWORK_CHAINS: [&str; 8] = ["root", "mac", "stp", "vlan", "arp", "rarp", "ipv4", "ipv6"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Directory where nat rules are stored, inside storage directory
 | 
				
			||||||
 | 
					pub const STORAGE_NAT_DIR: &str = "nat";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,4 +7,5 @@ pub mod libvirt_client;
 | 
				
			|||||||
pub mod libvirt_lib_structures;
 | 
					pub mod libvirt_lib_structures;
 | 
				
			||||||
pub mod libvirt_rest_structures;
 | 
					pub mod libvirt_rest_structures;
 | 
				
			||||||
pub mod middlewares;
 | 
					pub mod middlewares;
 | 
				
			||||||
 | 
					pub mod nat;
 | 
				
			||||||
pub mod utils;
 | 
					pub mod utils;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
use crate::libvirt_lib_structures::network::*;
 | 
					use crate::libvirt_lib_structures::network::*;
 | 
				
			||||||
use crate::libvirt_lib_structures::XMLUuid;
 | 
					use crate::libvirt_lib_structures::XMLUuid;
 | 
				
			||||||
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction;
 | 
					use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction;
 | 
				
			||||||
 | 
					use crate::nat::nat_definition::Nat;
 | 
				
			||||||
 | 
					use crate::nat::nat_lib;
 | 
				
			||||||
use crate::utils::net_utils::{extract_ipv4, extract_ipv6};
 | 
					use crate::utils::net_utils::{extract_ipv4, extract_ipv6};
 | 
				
			||||||
use ipnetwork::{Ipv4Network, Ipv6Network};
 | 
					use ipnetwork::{Ipv4Network, Ipv6Network};
 | 
				
			||||||
use lazy_regex::regex;
 | 
					use lazy_regex::regex;
 | 
				
			||||||
@@ -21,57 +23,68 @@ pub struct DHCPv4HostReservation {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
				
			||||||
pub struct IPv4DHCPConfig {
 | 
					pub struct IPv4DHCPConfig {
 | 
				
			||||||
    start: Ipv4Addr,
 | 
					    pub start: Ipv4Addr,
 | 
				
			||||||
    end: Ipv4Addr,
 | 
					    pub end: Ipv4Addr,
 | 
				
			||||||
    hosts: Vec<DHCPv4HostReservation>,
 | 
					    pub hosts: Vec<DHCPv4HostReservation>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
				
			||||||
pub struct IPV4Config {
 | 
					pub struct IPV4Config {
 | 
				
			||||||
    bridge_address: Ipv4Addr,
 | 
					    pub bridge_address: Ipv4Addr,
 | 
				
			||||||
    prefix: u32,
 | 
					    pub prefix: u32,
 | 
				
			||||||
    dhcp: Option<IPv4DHCPConfig>,
 | 
					    pub dhcp: Option<IPv4DHCPConfig>,
 | 
				
			||||||
 | 
					    pub nat: Option<Vec<Nat<Ipv4Addr>>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
				
			||||||
pub struct DHCPv6HostReservation {
 | 
					pub struct DHCPv6HostReservation {
 | 
				
			||||||
    name: String,
 | 
					    pub name: String,
 | 
				
			||||||
    ip: Ipv6Addr,
 | 
					    pub ip: Ipv6Addr,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
				
			||||||
pub struct IPv6DHCPConfig {
 | 
					pub struct IPv6DHCPConfig {
 | 
				
			||||||
    start: Ipv6Addr,
 | 
					    pub start: Ipv6Addr,
 | 
				
			||||||
    end: Ipv6Addr,
 | 
					    pub end: Ipv6Addr,
 | 
				
			||||||
    hosts: Vec<DHCPv6HostReservation>,
 | 
					    pub hosts: Vec<DHCPv6HostReservation>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
				
			||||||
pub struct IPV6Config {
 | 
					pub struct IPV6Config {
 | 
				
			||||||
    bridge_address: Ipv6Addr,
 | 
					    pub bridge_address: Ipv6Addr,
 | 
				
			||||||
    prefix: u32,
 | 
					    pub prefix: u32,
 | 
				
			||||||
    dhcp: Option<IPv6DHCPConfig>,
 | 
					    pub dhcp: Option<IPv6DHCPConfig>,
 | 
				
			||||||
 | 
					    pub nat: Option<Vec<Nat<Ipv6Addr>>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct NetworkName(pub String);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl NetworkName {
 | 
				
			||||||
 | 
					    pub fn is_valid(&self) -> bool {
 | 
				
			||||||
 | 
					        regex!("^[a-zA-Z0-9]+$").is_match(&self.0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Network configuration
 | 
					/// Network configuration
 | 
				
			||||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
					#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
 | 
				
			||||||
pub struct NetworkInfo {
 | 
					pub struct NetworkInfo {
 | 
				
			||||||
    pub name: String,
 | 
					    pub name: NetworkName,
 | 
				
			||||||
    pub uuid: Option<XMLUuid>,
 | 
					    pub uuid: Option<XMLUuid>,
 | 
				
			||||||
    title: Option<String>,
 | 
					    pub title: Option<String>,
 | 
				
			||||||
    description: Option<String>,
 | 
					    pub description: Option<String>,
 | 
				
			||||||
    forward_mode: NetworkForwardMode,
 | 
					    pub forward_mode: NetworkForwardMode,
 | 
				
			||||||
    device: Option<String>,
 | 
					    pub device: Option<String>,
 | 
				
			||||||
    bridge_name: Option<String>,
 | 
					    pub bridge_name: Option<String>,
 | 
				
			||||||
    dns_server: Option<Ipv4Addr>,
 | 
					    pub dns_server: Option<Ipv4Addr>,
 | 
				
			||||||
    domain: Option<String>,
 | 
					    pub domain: Option<String>,
 | 
				
			||||||
    ip_v4: Option<IPV4Config>,
 | 
					    pub ip_v4: Option<IPV4Config>,
 | 
				
			||||||
    ip_v6: Option<IPV6Config>,
 | 
					    pub ip_v6: Option<IPV6Config>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl NetworkInfo {
 | 
					impl NetworkInfo {
 | 
				
			||||||
    pub fn as_virt_network(&self) -> anyhow::Result<NetworkXML> {
 | 
					    pub fn as_virt_network(&self) -> anyhow::Result<NetworkXML> {
 | 
				
			||||||
        if !regex!("^[a-zA-Z0-9]+$").is_match(&self.name) {
 | 
					        if !self.name.is_valid() {
 | 
				
			||||||
            return Err(StructureExtraction("network name is invalid!").into());
 | 
					            return Err(StructureExtraction("network name is invalid!").into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -160,7 +173,7 @@ impl NetworkInfo {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(NetworkXML {
 | 
					        Ok(NetworkXML {
 | 
				
			||||||
            name: self.name.to_string(),
 | 
					            name: self.name.0.to_string(),
 | 
				
			||||||
            uuid: self.uuid,
 | 
					            uuid: self.uuid,
 | 
				
			||||||
            title: self.title.clone(),
 | 
					            title: self.title.clone(),
 | 
				
			||||||
            description: self.description.clone(),
 | 
					            description: self.description.clone(),
 | 
				
			||||||
@@ -183,8 +196,12 @@ impl NetworkInfo {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn from_xml(xml: NetworkXML) -> anyhow::Result<Self> {
 | 
					    pub fn from_xml(xml: NetworkXML) -> anyhow::Result<Self> {
 | 
				
			||||||
 | 
					        let name = NetworkName(xml.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let nat = nat_lib::load_nat_def(&name)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Self {
 | 
					        Ok(Self {
 | 
				
			||||||
            name: xml.name,
 | 
					            name,
 | 
				
			||||||
            uuid: xml.uuid,
 | 
					            uuid: xml.uuid,
 | 
				
			||||||
            title: xml.title,
 | 
					            title: xml.title,
 | 
				
			||||||
            description: xml.description,
 | 
					            description: xml.description,
 | 
				
			||||||
@@ -227,6 +244,7 @@ impl NetworkInfo {
 | 
				
			|||||||
                            })
 | 
					                            })
 | 
				
			||||||
                            .collect(),
 | 
					                            .collect(),
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
 | 
					                    nat: nat.ipv4,
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
            ip_v6: xml
 | 
					            ip_v6: xml
 | 
				
			||||||
                .ips
 | 
					                .ips
 | 
				
			||||||
@@ -252,7 +270,25 @@ impl NetworkInfo {
 | 
				
			|||||||
                            })
 | 
					                            })
 | 
				
			||||||
                            .collect(),
 | 
					                            .collect(),
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
 | 
					                    nat: nat.ipv6,
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Check if at least one NAT definition was specified on this interface
 | 
				
			||||||
 | 
					    pub fn has_nat_def(&self) -> bool {
 | 
				
			||||||
 | 
					        if let Some(ipv4) = &self.ip_v4 {
 | 
				
			||||||
 | 
					            if ipv4.nat.is_some() {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Some(ipv6) = &self.ip_v6 {
 | 
				
			||||||
 | 
					            if ipv6.nat.is_some() {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,7 @@ async fn main() -> std::io::Result<()> {
 | 
				
			|||||||
    files_utils::create_directory_if_missing(AppConfig::get().vnc_sockets_path()).unwrap();
 | 
					    files_utils::create_directory_if_missing(AppConfig::get().vnc_sockets_path()).unwrap();
 | 
				
			||||||
    files_utils::set_file_permission(AppConfig::get().vnc_sockets_path(), 0o777).unwrap();
 | 
					    files_utils::set_file_permission(AppConfig::get().vnc_sockets_path(), 0o777).unwrap();
 | 
				
			||||||
    files_utils::create_directory_if_missing(AppConfig::get().disks_storage_path()).unwrap();
 | 
					    files_utils::create_directory_if_missing(AppConfig::get().disks_storage_path()).unwrap();
 | 
				
			||||||
 | 
					    files_utils::create_directory_if_missing(AppConfig::get().nat_path()).unwrap();
 | 
				
			||||||
    files_utils::create_directory_if_missing(AppConfig::get().definitions_path()).unwrap();
 | 
					    files_utils::create_directory_if_missing(AppConfig::get().definitions_path()).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let conn = Data::new(LibVirtClient(
 | 
					    let conn = Data::new(LibVirtClient(
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								virtweb_backend/src/nat/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								virtweb_backend/src/nat/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					pub mod nat_definition;
 | 
				
			||||||
 | 
					pub mod nat_lib;
 | 
				
			||||||
							
								
								
									
										39
									
								
								virtweb_backend/src/nat/nat_definition.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								virtweb_backend/src/nat/nat_definition.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					use std::net::{Ipv4Addr, Ipv6Addr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
 | 
					#[serde(tag = "type", rename_all = "lowercase")]
 | 
				
			||||||
 | 
					pub enum NatSource<IPv> {
 | 
				
			||||||
 | 
					    Interface { name: String },
 | 
				
			||||||
 | 
					    Ip { ip: IPv },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
 | 
					pub enum NatProtocol {
 | 
				
			||||||
 | 
					    TCP,
 | 
				
			||||||
 | 
					    UDP,
 | 
				
			||||||
 | 
					    Both,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
 | 
					#[serde(tag = "type", rename_all = "lowercase")]
 | 
				
			||||||
 | 
					pub enum NatHostPort {
 | 
				
			||||||
 | 
					    Single { port: u16 },
 | 
				
			||||||
 | 
					    Range { start: u16, end: u16 },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
 | 
					pub struct Nat<IPv> {
 | 
				
			||||||
 | 
					    pub protocol: NatProtocol,
 | 
				
			||||||
 | 
					    pub host_addr: NatSource<IPv>,
 | 
				
			||||||
 | 
					    pub host_port: NatHostPort,
 | 
				
			||||||
 | 
					    pub guest_addr: IPv,
 | 
				
			||||||
 | 
					    pub guest_port: u16,
 | 
				
			||||||
 | 
					    pub comment: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
 | 
				
			||||||
 | 
					pub struct NetNat {
 | 
				
			||||||
 | 
					    pub interface: String,
 | 
				
			||||||
 | 
					    pub ipv4: Option<Vec<Nat<Ipv4Addr>>>,
 | 
				
			||||||
 | 
					    pub ipv6: Option<Vec<Nat<Ipv6Addr>>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								virtweb_backend/src/nat/nat_lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								virtweb_backend/src/nat/nat_lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					use crate::app_config::AppConfig;
 | 
				
			||||||
 | 
					use crate::libvirt_rest_structures::net::{NetworkInfo, NetworkName};
 | 
				
			||||||
 | 
					use crate::nat::nat_definition::NetNat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(thiserror::Error, Debug)]
 | 
				
			||||||
 | 
					enum NatLibError {
 | 
				
			||||||
 | 
					    #[error("Could not save nat definition, because network bridge name was not specified!")]
 | 
				
			||||||
 | 
					    MissingNetworkBridgeName,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Save nat definition
 | 
				
			||||||
 | 
					pub fn save_nat_def(net: &NetworkInfo) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let nat = match net.has_nat_def() {
 | 
				
			||||||
 | 
					        true => NetNat {
 | 
				
			||||||
 | 
					            interface: net
 | 
				
			||||||
 | 
					                .bridge_name
 | 
				
			||||||
 | 
					                .as_ref()
 | 
				
			||||||
 | 
					                .ok_or(NatLibError::MissingNetworkBridgeName)?
 | 
				
			||||||
 | 
					                .to_string(),
 | 
				
			||||||
 | 
					            ipv4: net
 | 
				
			||||||
 | 
					                .ip_v4
 | 
				
			||||||
 | 
					                .as_ref()
 | 
				
			||||||
 | 
					                .map(|i| i.nat.clone())
 | 
				
			||||||
 | 
					                .unwrap_or_default(),
 | 
				
			||||||
 | 
					            ipv6: net
 | 
				
			||||||
 | 
					                .ip_v6
 | 
				
			||||||
 | 
					                .as_ref()
 | 
				
			||||||
 | 
					                .map(|i| i.nat.clone())
 | 
				
			||||||
 | 
					                .unwrap_or_default(),
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        false => NetNat::default(),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let json = serde_json::to_string(&nat)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::fs::write(AppConfig::get().net_nat_path(&net.name), json)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Remove nat definition, if existing
 | 
				
			||||||
 | 
					pub fn remove_nat_def(name: &NetworkName) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let nat_file = AppConfig::get().net_nat_path(name);
 | 
				
			||||||
 | 
					    if nat_file.exists() {
 | 
				
			||||||
 | 
					        std::fs::remove_file(nat_file)?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Load nat definition, if available
 | 
				
			||||||
 | 
					pub fn load_nat_def(name: &NetworkName) -> anyhow::Result<NetNat> {
 | 
				
			||||||
 | 
					    let nat_file = AppConfig::get().net_nat_path(name);
 | 
				
			||||||
 | 
					    if !nat_file.exists() {
 | 
				
			||||||
 | 
					        return Ok(NetNat::default());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let file = std::fs::read_to_string(nat_file)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(serde_json::from_str(&file)?)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user