]> git.proxmox.com Git - proxmox-backup.git/blob - src/api2/config/datastore.rs
followup: commit all changes
[proxmox-backup.git] / src / api2 / config / datastore.rs
1 use std::path::PathBuf;
2
3 use failure::*;
4 use serde_json::Value;
5
6 use proxmox::api::{api, ApiMethod, Router, RpcEnvironment};
7
8 use crate::api2::types::*;
9 use crate::backup::*;
10 use crate::config::datastore;
11
12 #[api(
13 input: {
14 properties: {},
15 },
16 returns: {
17 description: "List the configured datastores (with config digest).",
18 type: Array,
19 items: {
20 type: datastore::DataStoreConfig,
21 },
22 },
23 )]
24 /// List all datastores
25 pub fn list_datastores(
26 _param: Value,
27 _info: &ApiMethod,
28 _rpcenv: &mut dyn RpcEnvironment,
29 ) -> Result<Value, Error> {
30
31 let (config, digest) = datastore::config()?;
32
33 Ok(config.convert_to_array("name", Some(&digest)))
34 }
35
36 #[api(
37 protected: true,
38 input: {
39 properties: {
40 name: {
41 schema: DATASTORE_SCHEMA,
42 },
43 comment: {
44 optional: true,
45 schema: SINGLE_LINE_COMMENT_SCHEMA,
46 },
47 path: {
48 schema: datastore::DIR_NAME_SCHEMA,
49 },
50 },
51 },
52 )]
53 /// Create new datastore config.
54 pub fn create_datastore(name: String, param: Value) -> Result<(), Error> {
55
56 let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
57
58 let datastore: datastore::DataStoreConfig = serde_json::from_value(param.clone())?;
59
60 let (mut config, _digest) = datastore::config()?;
61
62 if let Some(_) = config.sections.get(&name) {
63 bail!("datastore '{}' already exists.", name);
64 }
65
66 let path: PathBuf = datastore.path.clone().into();
67
68 let backup_user = crate::backup::backup_user()?;
69 let _store = ChunkStore::create(&name, path, backup_user.uid, backup_user.gid)?;
70
71 config.set_data(&name, "datastore", &datastore)?;
72
73 datastore::save_config(&config)?;
74
75 Ok(())
76 }
77
78 #[api(
79 input: {
80 properties: {
81 name: {
82 schema: DATASTORE_SCHEMA,
83 },
84 },
85 },
86 returns: {
87 description: "The datastore configuration (with config digest).",
88 type: datastore::DataStoreConfig,
89 },
90 )]
91 /// Read a datastore configuration.
92 pub fn read_datastore(name: String) -> Result<Value, Error> {
93 let (config, digest) = datastore::config()?;
94 let mut data = config.lookup_json("datastore", &name)?;
95 data.as_object_mut().unwrap()
96 .insert("digest".into(), proxmox::tools::digest_to_hex(&digest).into());
97 Ok(data)
98 }
99
100 #[api(
101 protected: true,
102 input: {
103 properties: {
104 name: {
105 schema: DATASTORE_SCHEMA,
106 },
107 comment: {
108 optional: true,
109 schema: SINGLE_LINE_COMMENT_SCHEMA,
110 },
111 digest: {
112 optional: true,
113 schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
114 },
115 },
116 },
117 )]
118 /// Create new datastore config.
119 pub fn update_datastore(
120 name: String,
121 comment: Option<String>,
122 digest: Option<String>,
123 ) -> Result<(), Error> {
124
125 let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
126
127 // pass/compare digest
128 let (mut config, expected_digest) = datastore::config()?;
129
130 if let Some(ref digest) = digest {
131 let digest = proxmox::tools::hex_to_digest(digest)?;
132 crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
133 }
134
135 let mut data: datastore::DataStoreConfig = config.lookup("datastore", &name)?;
136
137 if let Some(comment) = comment {
138 let comment = comment.trim().to_string();
139 if comment.is_empty() {
140 data.comment = None;
141 } else {
142 data.comment = Some(comment);
143 }
144 }
145
146 config.set_data(&name, "datastore", &data)?;
147
148 datastore::save_config(&config)?;
149
150 Ok(())
151 }
152
153 #[api(
154 protected: true,
155 input: {
156 properties: {
157 name: {
158 schema: DATASTORE_SCHEMA,
159 },
160 },
161 },
162 )]
163 /// Remove a datastore configuration.
164 pub fn delete_datastore(name: String) -> Result<(), Error> {
165
166 // fixme: locking ?
167 // fixme: check digest ?
168
169 let (mut config, _digest) = datastore::config()?;
170
171 match config.sections.get(&name) {
172 Some(_) => { config.sections.remove(&name); },
173 None => bail!("datastore '{}' does not exist.", name),
174 }
175
176 datastore::save_config(&config)?;
177
178 Ok(())
179 }
180
181 const ITEM_ROUTER: Router = Router::new()
182 .get(&API_METHOD_READ_DATASTORE)
183 .put(&API_METHOD_UPDATE_DATASTORE)
184 .delete(&API_METHOD_DELETE_DATASTORE);
185
186 pub const ROUTER: Router = Router::new()
187 .get(&API_METHOD_LIST_DATASTORES)
188 .post(&API_METHOD_CREATE_DATASTORE)
189 .match_all("name", &ITEM_ROUTER);