]>
Commit | Line | Data |
---|---|---|
e9d2fc93 HL |
1 | use std::borrow::Cow; |
2 | use anyhow::{bail, Error}; | |
2a05c75f HL |
3 | use serde::{Deserialize, Serialize}; |
4 | ||
5 | use proxmox_schema::{api, ApiStringFormat, const_regex, Schema, StringSchema}; | |
6 | ||
7 | const_regex!{ | |
8 | pub MAINTENANCE_MESSAGE_REGEX = r"^[[:^cntrl:]]*$"; | |
9 | } | |
10 | ||
11 | pub const MAINTENANCE_MESSAGE_FORMAT: ApiStringFormat = | |
12 | ApiStringFormat::Pattern(&MAINTENANCE_MESSAGE_REGEX); | |
13 | ||
14 | ||
15 | pub const MAINTENANCE_MESSAGE_SCHEMA: Schema = | |
16 | StringSchema::new("Message describing the reason for the maintenance.") | |
17 | .format(&MAINTENANCE_MESSAGE_FORMAT) | |
18 | .max_length(64) | |
19 | .schema(); | |
20 | ||
21 | #[derive(Clone, Copy, Debug)] | |
22 | /// Operation requirements, used when checking for maintenance mode. | |
23 | pub enum Operation { | |
24 | Read, | |
25 | Write, | |
26 | } | |
27 | ||
28 | #[api] | |
e9d2fc93 | 29 | #[derive(Deserialize, Serialize, PartialEq)] |
2a05c75f HL |
30 | #[serde(rename_all="kebab-case")] |
31 | /// Maintenance type. | |
32 | pub enum MaintenanceType { | |
33 | /// Only read operations are allowed on the datastore. | |
34 | ReadOnly, | |
35 | /// Neither read nor write operations are allowed on the datastore. | |
36 | Offline, | |
37 | } | |
38 | ||
39 | #[api( | |
40 | properties: { | |
41 | type: { | |
42 | type: MaintenanceType, | |
43 | }, | |
44 | message: { | |
45 | optional: true, | |
46 | schema: MAINTENANCE_MESSAGE_SCHEMA, | |
47 | } | |
48 | }, | |
49 | default_key: "type", | |
50 | )] | |
51 | #[derive(Deserialize, Serialize)] | |
52 | /// Maintenance mode | |
53 | pub struct MaintenanceMode { | |
54 | /// Type of maintenance ("read-only" or "offline"). | |
55 | #[serde(rename = "type")] | |
56 | ty: MaintenanceType, | |
57 | ||
58 | /// Reason for maintenance. | |
59 | #[serde(skip_serializing_if = "Option::is_none")] | |
60 | message: Option<String>, | |
61 | } | |
e9d2fc93 HL |
62 | |
63 | impl MaintenanceMode { | |
64 | pub fn check(&self, operation: Option<Operation>) -> Result<(), Error> { | |
65 | let message = percent_encoding::percent_decode_str(self.message.as_deref().unwrap_or("")) | |
66 | .decode_utf8() | |
67 | .unwrap_or(Cow::Borrowed("")); | |
68 | ||
69 | if self.ty == MaintenanceType::Offline { | |
70 | bail!("offline maintenance mode: {}", message); | |
71 | } else if self.ty == MaintenanceType::ReadOnly { | |
72 | if let Some(Operation::Write) = operation { | |
73 | bail!("read-only maintenance mode: {}", message); | |
74 | } | |
75 | } | |
76 | Ok(()) | |
77 | } | |
78 | } |