]>
Commit | Line | Data |
---|---|---|
a35a211d DM |
1 | use anyhow::Error; |
2 | use serde_json::Value; | |
3 | ||
6ef1b649 WB |
4 | use proxmox_router::{cli::*, ApiHandler, RpcEnvironment}; |
5 | use proxmox_schema::api; | |
a35a211d | 6 | |
a35a211d DM |
7 | use proxmox_backup::api2; |
8 | ||
9 | #[api( | |
10 | input: { | |
11 | properties: { | |
12 | "output-format": { | |
13 | schema: OUTPUT_FORMAT, | |
14 | optional: true, | |
15 | }, | |
16 | } | |
17 | } | |
18 | )] | |
19 | /// Network device list. | |
20 | fn list_network_devices(mut param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> { | |
21 | ||
22 | let output_format = get_output_format(¶m); | |
23 | ||
24 | param["node"] = "localhost".into(); | |
25 | ||
26 | let info = &api2::node::network::API_METHOD_LIST_NETWORK_DEVICES; | |
27 | let mut data = match info.handler { | |
28 | ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?, | |
29 | _ => unreachable!(), | |
30 | }; | |
31 | ||
32 | if let Value::String(ref diff) = rpcenv["changes"] { | |
33 | if output_format == "text" { | |
34 | eprintln!("pending changes:\n{}\n", diff); | |
35 | } | |
36 | } | |
37 | ||
38 | fn render_address(_value: &Value, record: &Value) -> Result<String, Error> { | |
39 | let mut text = String::new(); | |
40 | ||
41 | if let Some(cidr) = record["cidr"].as_str() { | |
42 | text.push_str(cidr); | |
43 | } | |
44 | if let Some(cidr) = record["cidr6"].as_str() { | |
45 | if !text.is_empty() { text.push('\n'); } | |
46 | text.push_str(cidr); | |
47 | } | |
48 | ||
49 | Ok(text) | |
50 | } | |
51 | ||
52 | fn render_ports(_value: &Value, record: &Value) -> Result<String, Error> { | |
53 | let mut text = String::new(); | |
54 | ||
55 | if let Some(ports) = record["bridge_ports"].as_array() { | |
56 | let list: Vec<&str> = ports.iter().filter_map(|v| v.as_str()).collect(); | |
57 | text.push_str(&list.join(" ")); | |
58 | } | |
59 | if let Some(slaves) = record["slaves"].as_array() { | |
60 | let list: Vec<&str> = slaves.iter().filter_map(|v| v.as_str()).collect(); | |
61 | text.push_str(&list.join(" ")); | |
62 | } | |
63 | ||
64 | Ok(text) | |
65 | } | |
66 | ||
67 | fn render_gateway(_value: &Value, record: &Value) -> Result<String, Error> { | |
68 | let mut text = String::new(); | |
69 | ||
70 | if let Some(gateway) = record["gateway"].as_str() { | |
71 | text.push_str(gateway); | |
72 | } | |
73 | if let Some(gateway) = record["gateway6"].as_str() { | |
74 | if !text.is_empty() { text.push('\n'); } | |
75 | text.push_str(gateway); | |
76 | } | |
77 | ||
78 | Ok(text) | |
79 | } | |
80 | ||
81 | let options = default_table_format_options() | |
82 | .column(ColumnConfig::new("name")) | |
83 | .column(ColumnConfig::new("type").header("type")) | |
84 | .column(ColumnConfig::new("autostart")) | |
85 | .column(ColumnConfig::new("method")) | |
86 | .column(ColumnConfig::new("method6")) | |
87 | .column(ColumnConfig::new("cidr").header("address").renderer(render_address)) | |
88 | .column(ColumnConfig::new("gateway").header("gateway").renderer(render_gateway)) | |
89 | .column(ColumnConfig::new("bridge_ports").header("ports/slaves").renderer(render_ports)); | |
90 | ||
b2362a12 | 91 | format_and_print_result_full(&mut data, &info.returns, &output_format, &options); |
a35a211d DM |
92 | |
93 | Ok(Value::Null) | |
94 | } | |
95 | ||
96 | #[api()] | |
97 | /// Show pending configuration changes (diff) | |
98 | fn pending_network_changes(mut param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> { | |
99 | param["node"] = "localhost".into(); | |
100 | ||
101 | let info = &api2::node::network::API_METHOD_LIST_NETWORK_DEVICES; | |
102 | let _data = match info.handler { | |
103 | ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?, | |
104 | _ => unreachable!(), | |
105 | }; | |
106 | ||
107 | if let Value::String(ref diff) = rpcenv["changes"] { | |
108 | println!("{}", diff); | |
109 | } | |
110 | ||
111 | Ok(Value::Null) | |
112 | } | |
113 | ||
114 | pub fn network_commands() -> CommandLineInterface { | |
115 | ||
116 | let cmd_def = CliCommandMap::new() | |
117 | .insert( | |
118 | "list", | |
119 | CliCommand::new(&API_METHOD_LIST_NETWORK_DEVICES) | |
120 | ) | |
121 | .insert( | |
122 | "changes", | |
123 | CliCommand::new(&API_METHOD_PENDING_NETWORK_CHANGES) | |
124 | ) | |
125 | .insert( | |
126 | "create", | |
127 | CliCommand::new(&api2::node::network::API_METHOD_CREATE_INTERFACE) | |
128 | .fixed_param("node", String::from("localhost")) | |
129 | .arg_param(&["iface"]) | |
6f422880 DM |
130 | .completion_cb("iface", pbs_config::network::complete_interface_name) |
131 | .completion_cb("bridge_ports", pbs_config::network::complete_port_list) | |
132 | .completion_cb("slaves", pbs_config::network::complete_port_list) | |
a35a211d DM |
133 | ) |
134 | .insert( | |
135 | "update", | |
136 | CliCommand::new(&api2::node::network::API_METHOD_UPDATE_INTERFACE) | |
137 | .fixed_param("node", String::from("localhost")) | |
138 | .arg_param(&["iface"]) | |
6f422880 DM |
139 | .completion_cb("iface", pbs_config::network::complete_interface_name) |
140 | .completion_cb("bridge_ports", pbs_config::network::complete_port_list) | |
141 | .completion_cb("slaves", pbs_config::network::complete_port_list) | |
a35a211d DM |
142 | ) |
143 | .insert( | |
144 | "remove", | |
145 | CliCommand::new(&api2::node::network::API_METHOD_DELETE_INTERFACE) | |
146 | .fixed_param("node", String::from("localhost")) | |
147 | .arg_param(&["iface"]) | |
6f422880 | 148 | .completion_cb("iface", pbs_config::network::complete_interface_name) |
a35a211d DM |
149 | ) |
150 | .insert( | |
151 | "revert", | |
152 | CliCommand::new(&api2::node::network::API_METHOD_REVERT_NETWORK_CONFIG) | |
153 | .fixed_param("node", String::from("localhost")) | |
154 | ) | |
155 | .insert( | |
156 | "reload", | |
157 | CliCommand::new(&api2::node::network::API_METHOD_RELOAD_NETWORK_CONFIG) | |
158 | .fixed_param("node", String::from("localhost")) | |
159 | ); | |
160 | ||
161 | cmd_def.into() | |
162 | } |