1 use ::serde
::{Deserialize, Serialize}
;
6 use proxmox_router
::{http_bail, ApiMethod, Permission, Router, RpcEnvironment}
;
7 use proxmox_schema
::{api, param_bail}
;
10 TrafficControlRule
, TrafficControlRuleUpdater
, PRIV_SYS_AUDIT
, PRIV_SYS_MODIFY
,
11 PROXMOX_CONFIG_DIGEST_SCHEMA
, TRAFFIC_CONTROL_ID_SCHEMA
,
19 description
: "The list of configured traffic control rules (with config digest).",
21 items
: { type: TrafficControlRule }
,
24 permission
: &Permission
::Privilege(&[], PRIV_SYS_MODIFY
, false),
27 /// List traffic control rules
28 pub fn list_traffic_controls(
31 rpcenv
: &mut dyn RpcEnvironment
,
32 ) -> Result
<Vec
<TrafficControlRule
>, Error
> {
33 let (config
, digest
) = pbs_config
::traffic_control
::config()?
;
35 let list
: Vec
<TrafficControlRule
> = config
.convert_to_typed_array("rule")?
;
37 rpcenv
["digest"] = hex
::encode(digest
).into();
47 type: TrafficControlRule
,
53 permission
: &Permission
::Privilege(&[], PRIV_SYS_MODIFY
, false),
56 /// Create new traffic control rule.
57 pub fn create_traffic_control(config
: TrafficControlRule
) -> Result
<(), Error
> {
58 let _lock
= pbs_config
::traffic_control
::lock_config()?
;
60 let (mut section_config
, _digest
) = pbs_config
::traffic_control
::config()?
;
62 if section_config
.sections
.get(&config
.name
).is_some() {
65 "traffic control rule '{}' already exists.",
70 section_config
.set_data(&config
.name
, "rule", &config
)?
;
72 pbs_config
::traffic_control
::save_config(§ion_config
)?
;
81 schema
: TRAFFIC_CONTROL_ID_SCHEMA
,
85 returns
: { type: TrafficControlRule }
,
87 permission
: &Permission
::Privilege(&[], PRIV_SYS_AUDIT
, false),
90 /// Read traffic control configuration data.
91 pub fn read_traffic_control(
94 rpcenv
: &mut dyn RpcEnvironment
,
95 ) -> Result
<TrafficControlRule
, Error
> {
96 let (config
, digest
) = pbs_config
::traffic_control
::config()?
;
97 let data
: TrafficControlRule
= config
.lookup("rule", &name
)?
;
98 rpcenv
["digest"] = hex
::encode(digest
).into();
103 #[derive(Serialize, Deserialize)]
104 #[allow(non_camel_case_types)]
105 #[serde(rename_all = "kebab-case")]
106 /// Deletable property name
107 pub enum DeletableProperty
{
108 /// Delete the rate_in property.
110 /// Delete the burst_in property.
112 /// Delete the rate_out property.
114 /// Delete the burst_out property.
116 /// Delete the comment property.
118 /// Delete the timeframe property
122 // fixme: use TrafficControlUpdater
128 schema
: TRAFFIC_CONTROL_ID_SCHEMA
,
131 type: TrafficControlRuleUpdater
,
135 description
: "List of properties to delete.",
139 type: DeletableProperty
,
144 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
149 permission
: &Permission
::Privilege(&[], PRIV_SYS_MODIFY
, false),
152 /// Update traffic control configuration.
153 pub fn update_traffic_control(
155 update
: TrafficControlRuleUpdater
,
156 delete
: Option
<Vec
<DeletableProperty
>>,
157 digest
: Option
<String
>,
158 ) -> Result
<(), Error
> {
159 let _lock
= pbs_config
::traffic_control
::lock_config()?
;
161 let (mut config
, expected_digest
) = pbs_config
::traffic_control
::config()?
;
163 if let Some(ref digest
) = digest
{
164 let digest
= <[u8; 32]>::from_hex(digest
)?
;
165 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
168 let mut data
: TrafficControlRule
= config
.lookup("rule", &name
)?
;
170 if let Some(delete
) = delete
{
171 for delete_prop
in delete
{
173 DeletableProperty
::rate_in
=> {
174 data
.limit
.rate_in
= None
;
176 DeletableProperty
::rate_out
=> {
177 data
.limit
.rate_out
= None
;
179 DeletableProperty
::burst_in
=> {
180 data
.limit
.burst_in
= None
;
182 DeletableProperty
::burst_out
=> {
183 data
.limit
.burst_out
= None
;
185 DeletableProperty
::comment
=> {
188 DeletableProperty
::timeframe
=> {
189 data
.timeframe
= None
;
195 if let Some(comment
) = update
.comment
{
196 let comment
= comment
.trim().to_string();
197 if comment
.is_empty() {
200 data
.comment
= Some(comment
);
204 if update
.limit
.rate_in
.is_some() {
205 data
.limit
.rate_in
= update
.limit
.rate_in
;
208 if update
.limit
.rate_out
.is_some() {
209 data
.limit
.rate_out
= update
.limit
.rate_out
;
212 if update
.limit
.burst_in
.is_some() {
213 data
.limit
.burst_in
= update
.limit
.burst_in
;
216 if update
.limit
.burst_out
.is_some() {
217 data
.limit
.burst_out
= update
.limit
.burst_out
;
220 if let Some(network
) = update
.network
{
221 data
.network
= network
;
223 if update
.timeframe
.is_some() {
224 data
.timeframe
= update
.timeframe
;
227 config
.set_data(&name
, "rule", &data
)?
;
229 pbs_config
::traffic_control
::save_config(&config
)?
;
239 schema
: TRAFFIC_CONTROL_ID_SCHEMA
,
243 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
248 permission
: &Permission
::Privilege(&[], PRIV_SYS_MODIFY
, false),
251 /// Remove a traffic control rule from the configuration file.
252 pub fn delete_traffic_control(name
: String
, digest
: Option
<String
>) -> Result
<(), Error
> {
253 let _lock
= pbs_config
::traffic_control
::lock_config()?
;
255 let (mut config
, expected_digest
) = pbs_config
::traffic_control
::config()?
;
257 if let Some(ref digest
) = digest
{
258 let digest
= <[u8; 32]>::from_hex(digest
)?
;
259 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
262 match config
.sections
.get(&name
) {
264 config
.sections
.remove(&name
);
266 None
=> http_bail
!(NOT_FOUND
, "traffic control rule '{}' does not exist.", name
),
269 pbs_config
::traffic_control
::save_config(&config
)?
;
274 const ITEM_ROUTER
: Router
= Router
::new()
275 .get(&API_METHOD_READ_TRAFFIC_CONTROL
)
276 .put(&API_METHOD_UPDATE_TRAFFIC_CONTROL
)
277 .delete(&API_METHOD_DELETE_TRAFFIC_CONTROL
);
279 pub const ROUTER
: Router
= Router
::new()
280 .get(&API_METHOD_LIST_TRAFFIC_CONTROLS
)
281 .post(&API_METHOD_CREATE_TRAFFIC_CONTROL
)
282 .match_all("name", &ITEM_ROUTER
);