proxmox/proxmox-network-api/src/api_impl.rs
Maximiliano Sandoval aff76f9e0e remove needless borrows
Fixes the following clippy warnings:

warning: the borrowed expression implements the required traits
  --> proxmox-tfa/src/api/recovery.rs:86:24
   |
86 |         Ok(hex::encode(&hmac))
   |                        ^^^^^ help: change this to: `hmac`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args

and

warning: this expression creates a reference which is immediately dereferenced by the compiler
   --> proxmox-network-api/src/api_impl.rs:108:47
    |
108 |                 interface.set_bond_slave_list(&slaves)?;
    |                                               ^^^^^^^ help: change this to: `slaves`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
    = note: `#[warn(clippy::needless_borrow)]` on by default

Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
2024-06-28 10:22:58 +02:00

348 lines
11 KiB
Rust

use anyhow::{bail, Error};
use proxmox_config_digest::ConfigDigest;
use crate::{parse_vlan_id_from_name, parse_vlan_raw_device_from_name};
use crate::{
DeletableInterfaceProperty, Interface, InterfaceUpdater, LinuxBondMode, NetworkConfigMethod,
NetworkInterfaceType,
};
/// Create network interface configuration.
pub fn create_interface(iface: String, config: InterfaceUpdater) -> Result<(), Error> {
let interface_type = match config.interface_type {
Some(interface_type) => interface_type,
None => bail!("missing parameter 'type'"),
};
let _lock = crate::lock_config()?;
let (mut network_config, _digest) = crate::config()?;
if network_config.interfaces.contains_key(&iface) {
bail!("interface '{}' already exists", iface);
}
let mut interface = Interface::new(iface.clone());
interface.interface_type = interface_type;
if let Some(autostart) = config.autostart {
interface.autostart = autostart;
}
if config.method.is_some() {
interface.method = config.method;
}
if config.method6.is_some() {
interface.method6 = config.method6;
}
if config.mtu.is_some() {
interface.mtu = config.mtu;
}
if config.comments.is_some() {
interface.comments = config.comments;
}
if config.comments6.is_some() {
interface.comments6 = config.comments6;
}
if let Some(cidr) = config.cidr {
let (_, _, is_v6) = crate::parse_cidr(&cidr)?;
if is_v6 {
bail!("invalid address type (expected IPv4, got IPv6)");
}
interface.cidr = Some(cidr);
}
if let Some(cidr6) = config.cidr6 {
let (_, _, is_v6) = crate::parse_cidr(&cidr6)?;
if !is_v6 {
bail!("invalid address type (expected IPv6, got IPv4)");
}
interface.cidr6 = Some(cidr6);
}
if let Some(gateway) = config.gateway {
let is_v6 = gateway.contains(':');
if is_v6 {
bail!("invalid address type (expected IPv4, got IPv6)");
}
network_config.check_duplicate_gateway_v4(&iface)?;
interface.gateway = Some(gateway);
}
if let Some(gateway6) = config.gateway6 {
let is_v6 = gateway6.contains(':');
if !is_v6 {
bail!("invalid address type (expected IPv6, got IPv4)");
}
network_config.check_duplicate_gateway_v6(&iface)?;
interface.gateway6 = Some(gateway6);
}
match interface_type {
NetworkInterfaceType::Bridge => {
if let Some(ports) = &config.bridge_ports {
interface.set_bridge_port_list(ports)?;
}
if config.bridge_vlan_aware.is_some() {
interface.bridge_vlan_aware = config.bridge_vlan_aware;
}
}
NetworkInterfaceType::Bond => {
if let Some(mode) = config.bond_mode {
interface.bond_mode = config.bond_mode;
if config.bond_primary.is_some() {
if mode != LinuxBondMode::ActiveBackup {
bail!("bond-primary is only valid with Active/Backup mode");
}
interface.bond_primary = config.bond_primary;
}
if config.bond_xmit_hash_policy.is_some() {
if mode != LinuxBondMode::Ieee802_3ad && mode != LinuxBondMode::BalanceXor {
bail!("bond_xmit_hash_policy is only valid with LACP(802.3ad) or balance-xor mode");
}
interface.bond_xmit_hash_policy = config.bond_xmit_hash_policy;
}
}
if let Some(slaves) = &config.slaves {
interface.set_bond_slave_list(slaves)?;
}
}
NetworkInterfaceType::Vlan => {
if config.vlan_id.is_none() && parse_vlan_id_from_name(&iface).is_none() {
bail!("vlan-id must be set");
}
interface.vlan_id = config.vlan_id;
if let Some(dev) = config
.vlan_raw_device
.as_deref()
.or_else(|| parse_vlan_raw_device_from_name(&iface))
{
if !network_config.interfaces.contains_key(dev) {
bail!("vlan-raw-device {dev} does not exist");
}
} else {
bail!("vlan-raw-device must be set");
}
interface.vlan_raw_device = config.vlan_raw_device;
}
_ => bail!(
"creating network interface type '{:?}' is not supported",
interface_type
),
}
if interface.cidr.is_some() || interface.gateway.is_some() {
interface.method = Some(NetworkConfigMethod::Static);
} else if interface.method.is_none() {
interface.method = Some(NetworkConfigMethod::Manual);
}
if interface.cidr6.is_some() || interface.gateway6.is_some() {
interface.method6 = Some(NetworkConfigMethod::Static);
} else if interface.method6.is_none() {
interface.method6 = Some(NetworkConfigMethod::Manual);
}
network_config.interfaces.insert(iface, interface);
crate::save_config(&network_config)?;
Ok(())
}
/// Update network interface config.
pub fn update_interface(
iface: String,
update: InterfaceUpdater,
delete: Option<Vec<DeletableInterfaceProperty>>,
digest: Option<ConfigDigest>,
) -> Result<(), Error> {
let _lock = crate::lock_config()?;
let (mut network_config, expected_digest) = crate::config()?;
expected_digest.detect_modification(digest.as_ref())?;
if update.gateway.is_some() {
network_config.check_duplicate_gateway_v4(&iface)?;
}
if update.gateway6.is_some() {
network_config.check_duplicate_gateway_v6(&iface)?;
}
if let Some(dev) = update
.vlan_raw_device
.as_deref()
.or_else(|| parse_vlan_raw_device_from_name(&iface))
{
if !network_config.interfaces.contains_key(dev) {
bail!("vlan-raw-device {dev} does not exist");
}
}
let interface = network_config.lookup_mut(&iface)?;
if let Some(interface_type) = update.interface_type {
if interface_type != interface.interface_type {
bail!(
"got unexpected interface type ({:?} != {:?})",
interface_type,
interface.interface_type
);
}
}
if let Some(delete) = delete {
for delete_prop in delete {
match delete_prop {
DeletableInterfaceProperty::Cidr => {
interface.cidr = None;
}
DeletableInterfaceProperty::Cidr6 => {
interface.cidr6 = None;
}
DeletableInterfaceProperty::Gateway => {
interface.gateway = None;
}
DeletableInterfaceProperty::Gateway6 => {
interface.gateway6 = None;
}
DeletableInterfaceProperty::Method => {
interface.method = None;
}
DeletableInterfaceProperty::Method6 => {
interface.method6 = None;
}
DeletableInterfaceProperty::Comments => {
interface.comments = None;
}
DeletableInterfaceProperty::Comments6 => {
interface.comments6 = None;
}
DeletableInterfaceProperty::Mtu => {
interface.mtu = None;
}
DeletableInterfaceProperty::Autostart => {
interface.autostart = false;
}
DeletableInterfaceProperty::BridgePorts => {
interface.set_bridge_ports(Vec::new())?;
}
DeletableInterfaceProperty::BridgeVlanAware => {
interface.bridge_vlan_aware = None;
}
DeletableInterfaceProperty::Slaves => {
interface.set_bond_slaves(Vec::new())?;
}
DeletableInterfaceProperty::BondPrimary => {
interface.bond_primary = None;
}
DeletableInterfaceProperty::BondXmitHashPolicy => {
interface.bond_xmit_hash_policy = None
}
}
}
}
if let Some(autostart) = update.autostart {
interface.autostart = autostart;
}
if update.method.is_some() {
interface.method = update.method;
}
if update.method6.is_some() {
interface.method6 = update.method6;
}
if update.mtu.is_some() {
interface.mtu = update.mtu;
}
if let Some(ports) = &update.bridge_ports {
interface.set_bridge_port_list(ports)?;
}
if update.bridge_vlan_aware.is_some() {
interface.bridge_vlan_aware = update.bridge_vlan_aware;
}
if let Some(slaves) = &update.slaves {
interface.set_bond_slave_list(slaves)?;
}
if let Some(mode) = update.bond_mode {
interface.bond_mode = update.bond_mode;
if update.bond_primary.is_some() {
if mode != LinuxBondMode::ActiveBackup {
bail!("bond-primary is only valid with Active/Backup mode");
}
interface.bond_primary = update.bond_primary;
}
if update.bond_xmit_hash_policy.is_some() {
if mode != LinuxBondMode::Ieee802_3ad && mode != LinuxBondMode::BalanceXor {
bail!("bond_xmit_hash_policy is only valid with LACP(802.3ad) or balance-xor mode");
}
interface.bond_xmit_hash_policy = update.bond_xmit_hash_policy;
}
}
if let Some(cidr) = update.cidr {
let (_, _, is_v6) = crate::parse_cidr(&cidr)?;
if is_v6 {
bail!("invalid address type (expected IPv4, got IPv6)");
}
interface.cidr = Some(cidr);
}
if let Some(cidr6) = update.cidr6 {
let (_, _, is_v6) = crate::parse_cidr(&cidr6)?;
if !is_v6 {
bail!("invalid address type (expected IPv6, got IPv4)");
}
interface.cidr6 = Some(cidr6);
}
if let Some(gateway) = update.gateway {
let is_v6 = gateway.contains(':');
if is_v6 {
bail!("invalid address type (expected IPv4, got IPv6)");
}
interface.gateway = Some(gateway);
}
if let Some(gateway6) = update.gateway6 {
let is_v6 = gateway6.contains(':');
if !is_v6 {
bail!("invalid address type (expected IPv6, got IPv4)");
}
interface.gateway6 = Some(gateway6);
}
if update.comments.is_some() {
interface.comments = update.comments;
}
if update.comments6.is_some() {
interface.comments6 = update.comments6;
}
if interface.cidr.is_some() || interface.gateway.is_some() {
interface.method = Some(NetworkConfigMethod::Static);
} else {
interface.method = Some(NetworkConfigMethod::Manual);
}
if interface.cidr6.is_some() || interface.gateway6.is_some() {
interface.method6 = Some(NetworkConfigMethod::Static);
} else {
interface.method6 = Some(NetworkConfigMethod::Manual);
}
if update.vlan_id.is_some() {
interface.vlan_id = update.vlan_id;
}
if update.vlan_raw_device.is_some() {
interface.vlan_raw_device = update.vlan_raw_device;
}
crate::save_config(&network_config)?;
Ok(())
}