]> git.proxmox.com Git - proxmox-backup.git/blame - pbs-api-types/src/maintenance.rs
datastore: add check for maintenance in lookup
[proxmox-backup.git] / pbs-api-types / src / maintenance.rs
CommitLineData
e9d2fc93
HL
1use std::borrow::Cow;
2use anyhow::{bail, Error};
2a05c75f
HL
3use serde::{Deserialize, Serialize};
4
5use proxmox_schema::{api, ApiStringFormat, const_regex, Schema, StringSchema};
6
7const_regex!{
8 pub MAINTENANCE_MESSAGE_REGEX = r"^[[:^cntrl:]]*$";
9}
10
11pub const MAINTENANCE_MESSAGE_FORMAT: ApiStringFormat =
12 ApiStringFormat::Pattern(&MAINTENANCE_MESSAGE_REGEX);
13
14
15pub 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.
23pub 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.
32pub 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
53pub 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
63impl 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}