From ca0e5347963c08170f01966d16414d09260f6352 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Tue, 21 Apr 2020 14:28:26 +0200 Subject: [PATCH] src/api2/config/network.rs: start network configuration api --- src/api2/config.rs | 2 + src/api2/config/network.rs | 47 ++++++++++++++++++++ src/bin/proxmox-backup-manager.rs | 9 ++++ src/config/network.rs | 71 +++++++++++++++++++++++++++++-- 4 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/api2/config/network.rs diff --git a/src/api2/config.rs b/src/api2/config.rs index 79db82da..3f3f54c8 100644 --- a/src/api2/config.rs +++ b/src/api2/config.rs @@ -3,9 +3,11 @@ use proxmox::list_subdirs_api_method; pub mod datastore; pub mod remote; +pub mod network; const SUBDIRS: SubdirMap = &[ ("datastore", &datastore::ROUTER), + ("network", &network::ROUTER), ("remote", &remote::ROUTER), ]; diff --git a/src/api2/config/network.rs b/src/api2/config/network.rs new file mode 100644 index 00000000..8b06007a --- /dev/null +++ b/src/api2/config/network.rs @@ -0,0 +1,47 @@ +use anyhow::{Error}; +use serde_json::{Value, to_value}; + +use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission}; + +//use crate::api2::types::*; +use crate::config::network; +use crate::config::acl::{PRIV_SYS_AUDIT}; + +#[api( + input: { + properties: {}, + }, + returns: { + description: "List network devices (with config digest).", + type: Array, + items: { + type: network::Interface, + }, + }, + access: { + permission: &Permission::Privilege(&[], PRIV_SYS_AUDIT, false), + }, +)] +/// List all datastores +pub fn list_network_devices( + _param: Value, + _info: &ApiMethod, + _rpcenv: &mut dyn RpcEnvironment, +) -> Result { + + let (config, digest) = network::config()?; + let digest = proxmox::tools::digest_to_hex(&digest); + + let mut list = Vec::new(); + + for interface in config.interfaces.values() { + let mut item: Value = to_value(interface)?; + item["digest"] = digest.clone().into(); + list.push(item); + } + + Ok(list.into()) +} + +pub const ROUTER: Router = Router::new() + .get(&API_METHOD_LIST_NETWORK_DEVICES); diff --git a/src/bin/proxmox-backup-manager.rs b/src/bin/proxmox-backup-manager.rs index c71900d8..0f8164d3 100644 --- a/src/bin/proxmox-backup-manager.rs +++ b/src/bin/proxmox-backup-manager.rs @@ -233,6 +233,14 @@ fn acl_commands() -> CommandLineInterface { cmd_def.into() } +fn network_commands() -> CommandLineInterface { + + let cmd_def = CliCommandMap::new() + .insert("list", CliCommand::new(&api2::config::network::API_METHOD_LIST_NETWORK_DEVICES)); + + cmd_def.into() +} + fn datastore_commands() -> CommandLineInterface { let cmd_def = CliCommandMap::new() @@ -603,6 +611,7 @@ fn main() { let cmd_def = CliCommandMap::new() .insert("acl", acl_commands()) .insert("datastore", datastore_commands()) + .insert("network", network_commands()) .insert("user", user_commands()) .insert("remote", remote_commands()) .insert("garbage-collection", garbage_collection_commands()) diff --git a/src/config/network.rs b/src/config/network.rs index e6807fb5..1048550d 100644 --- a/src/config/network.rs +++ b/src/config/network.rs @@ -2,8 +2,10 @@ use std::io::{Write}; use std::collections::{HashSet, HashMap}; use anyhow::{Error, bail}; +use serde::{Serialize, Deserialize}; use proxmox::tools::{fs::replace_file, fs::CreateOptions}; +use proxmox::api::api; mod helper; pub use helper::*; @@ -14,29 +16,90 @@ pub use lexer::*; mod parser; pub use parser::*; -#[derive(Debug, Copy, Clone, PartialEq)] +#[api()] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +/// Interface configuration method pub enum ConfigMethod { + /// Configuration is done manually using other tools Manual, + /// Define interfaces with statically allocated addresses. Static, + /// Obtain an address via DHCP DHCP, + /// Define the loopback interface. Loopback, } -#[derive(Debug)] +#[api( + properties: { + name: { + type: String, + min_length: 1, + max_length: libc::IFNAMSIZ-1, + }, + method_v4: { + type: ConfigMethod, + optional: true, + }, + method_v6: { + type: ConfigMethod, + optional: true, + }, + options_v4: { + description: "Option list (inet)", + type: Array, + items: { + description: "Optional attribute.", + type: String, + }, + }, + options_v6: { + description: "Option list (inet6)", + type: Array, + items: { + description: "Optional attribute.", + type: String, + }, + }, + } +)] +#[derive(Debug, Serialize, Deserialize)] +/// Network Interface configuration pub struct Interface { + /// Autostart interface pub autostart: bool, + /// Interface is a physical network device pub exists: bool, + /// Interface is active (UP) pub active: bool, + /// Interface name pub name: String, - pub method_v4: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub method_v4: Option, + #[serde(skip_serializing_if="Option::is_none")] pub method_v6: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// IPv4 address pub address_v4: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// IPv4 gateway pub gateway_v4: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// IPv4 netmask pub netmask_v4: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// IPv6 address pub address_v6: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// IPv6 gateway pub gateway_v6: Option, + #[serde(skip_serializing_if="Option::is_none")] + /// IPv6 netmask pub netmask_v6: Option, + #[serde(skip_serializing_if="Vec::is_empty")] pub options_v4: Vec, + #[serde(skip_serializing_if="Vec::is_empty")] pub options_v6: Vec, } @@ -231,7 +294,7 @@ enum NetworkOrderEntry { #[derive(Debug)] pub struct NetworkConfig { - interfaces: HashMap, + pub interfaces: HashMap, order: Vec, }