src/api2/config/network.rs: start network configuration api
This commit is contained in:
parent
904e988667
commit
ca0e534796
|
@ -3,9 +3,11 @@ use proxmox::list_subdirs_api_method;
|
||||||
|
|
||||||
pub mod datastore;
|
pub mod datastore;
|
||||||
pub mod remote;
|
pub mod remote;
|
||||||
|
pub mod network;
|
||||||
|
|
||||||
const SUBDIRS: SubdirMap = &[
|
const SUBDIRS: SubdirMap = &[
|
||||||
("datastore", &datastore::ROUTER),
|
("datastore", &datastore::ROUTER),
|
||||||
|
("network", &network::ROUTER),
|
||||||
("remote", &remote::ROUTER),
|
("remote", &remote::ROUTER),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -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<Value, Error> {
|
||||||
|
|
||||||
|
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);
|
|
@ -233,6 +233,14 @@ fn acl_commands() -> CommandLineInterface {
|
||||||
cmd_def.into()
|
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 {
|
fn datastore_commands() -> CommandLineInterface {
|
||||||
|
|
||||||
let cmd_def = CliCommandMap::new()
|
let cmd_def = CliCommandMap::new()
|
||||||
|
@ -603,6 +611,7 @@ fn main() {
|
||||||
let cmd_def = CliCommandMap::new()
|
let cmd_def = CliCommandMap::new()
|
||||||
.insert("acl", acl_commands())
|
.insert("acl", acl_commands())
|
||||||
.insert("datastore", datastore_commands())
|
.insert("datastore", datastore_commands())
|
||||||
|
.insert("network", network_commands())
|
||||||
.insert("user", user_commands())
|
.insert("user", user_commands())
|
||||||
.insert("remote", remote_commands())
|
.insert("remote", remote_commands())
|
||||||
.insert("garbage-collection", garbage_collection_commands())
|
.insert("garbage-collection", garbage_collection_commands())
|
||||||
|
|
|
@ -2,8 +2,10 @@ use std::io::{Write};
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
|
|
||||||
use anyhow::{Error, bail};
|
use anyhow::{Error, bail};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use proxmox::tools::{fs::replace_file, fs::CreateOptions};
|
use proxmox::tools::{fs::replace_file, fs::CreateOptions};
|
||||||
|
use proxmox::api::api;
|
||||||
|
|
||||||
mod helper;
|
mod helper;
|
||||||
pub use helper::*;
|
pub use helper::*;
|
||||||
|
@ -14,29 +16,90 @@ pub use lexer::*;
|
||||||
mod parser;
|
mod parser;
|
||||||
pub use 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 {
|
pub enum ConfigMethod {
|
||||||
|
/// Configuration is done manually using other tools
|
||||||
Manual,
|
Manual,
|
||||||
|
/// Define interfaces with statically allocated addresses.
|
||||||
Static,
|
Static,
|
||||||
|
/// Obtain an address via DHCP
|
||||||
DHCP,
|
DHCP,
|
||||||
|
/// Define the loopback interface.
|
||||||
Loopback,
|
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 {
|
pub struct Interface {
|
||||||
|
/// Autostart interface
|
||||||
pub autostart: bool,
|
pub autostart: bool,
|
||||||
|
/// Interface is a physical network device
|
||||||
pub exists: bool,
|
pub exists: bool,
|
||||||
|
/// Interface is active (UP)
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
|
/// Interface name
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub method_v4: Option<ConfigMethod>,
|
pub method_v4: Option<ConfigMethod>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub method_v6: Option<ConfigMethod>,
|
pub method_v6: Option<ConfigMethod>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
/// IPv4 address
|
||||||
pub address_v4: Option<String>,
|
pub address_v4: Option<String>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
/// IPv4 gateway
|
||||||
pub gateway_v4: Option<String>,
|
pub gateway_v4: Option<String>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
/// IPv4 netmask
|
||||||
pub netmask_v4: Option<u8>,
|
pub netmask_v4: Option<u8>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
/// IPv6 address
|
||||||
pub address_v6: Option<String>,
|
pub address_v6: Option<String>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
/// IPv6 gateway
|
||||||
pub gateway_v6: Option<String>,
|
pub gateway_v6: Option<String>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
/// IPv6 netmask
|
||||||
pub netmask_v6: Option<u8>,
|
pub netmask_v6: Option<u8>,
|
||||||
|
#[serde(skip_serializing_if="Vec::is_empty")]
|
||||||
pub options_v4: Vec<String>,
|
pub options_v4: Vec<String>,
|
||||||
|
#[serde(skip_serializing_if="Vec::is_empty")]
|
||||||
pub options_v6: Vec<String>,
|
pub options_v6: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +294,7 @@ enum NetworkOrderEntry {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NetworkConfig {
|
pub struct NetworkConfig {
|
||||||
interfaces: HashMap<String, Interface>,
|
pub interfaces: HashMap<String, Interface>,
|
||||||
order: Vec<NetworkOrderEntry>,
|
order: Vec<NetworkOrderEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue