1 use std
::path
::PathBuf
;
3 use anyhow
::{bail, Error}
;
6 use proxmox
::api
::{api, ApiMethod, Router, RpcEnvironment, Permission}
;
8 use crate::api2
::types
::*;
10 use crate::config
::datastore
;
11 use crate::config
::acl
::{PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_ALLOCATE}
;
18 description
: "List the configured datastores (with config digest).",
21 type: datastore
::DataStoreConfig
,
25 permission
: &Permission
::Privilege(&["datastore"], PRIV_DATASTORE_AUDIT
, false),
28 /// List all datastores
29 pub fn list_datastores(
32 _rpcenv
: &mut dyn RpcEnvironment
,
33 ) -> Result
<Value
, Error
> {
35 let (config
, digest
) = datastore
::config()?
;
37 Ok(config
.convert_to_array("name", Some(&digest
), &[]))
45 schema
: DATASTORE_SCHEMA
,
49 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
52 schema
: datastore
::DIR_NAME_SCHEMA
,
57 permission
: &Permission
::Privilege(&["datastore"], PRIV_DATASTORE_ALLOCATE
, false),
60 /// Create new datastore config.
61 pub fn create_datastore(name
: String
, param
: Value
) -> Result
<(), Error
> {
63 let _lock
= crate::tools
::open_file_locked(datastore
::DATASTORE_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0))?
;
65 let datastore
: datastore
::DataStoreConfig
= serde_json
::from_value(param
.clone())?
;
67 let (mut config
, _digest
) = datastore
::config()?
;
69 if let Some(_
) = config
.sections
.get(&name
) {
70 bail
!("datastore '{}' already exists.", name
);
73 let path
: PathBuf
= datastore
.path
.clone().into();
75 let backup_user
= crate::backup
::backup_user()?
;
76 let _store
= ChunkStore
::create(&name
, path
, backup_user
.uid
, backup_user
.gid
)?
;
78 config
.set_data(&name
, "datastore", &datastore
)?
;
80 datastore
::save_config(&config
)?
;
89 schema
: DATASTORE_SCHEMA
,
94 description
: "The datastore configuration (with config digest).",
95 type: datastore
::DataStoreConfig
,
98 permission
: &Permission
::Privilege(&["datastore", "{name}"], PRIV_DATASTORE_AUDIT
, false),
101 /// Read a datastore configuration.
102 pub fn read_datastore(name
: String
) -> Result
<Value
, Error
> {
103 let (config
, digest
) = datastore
::config()?
;
104 let mut data
= config
.lookup_json("datastore", &name
)?
;
105 data
.as_object_mut().unwrap()
106 .insert("digest".into(), proxmox
::tools
::digest_to_hex(&digest
).into());
115 schema
: DATASTORE_SCHEMA
,
119 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
123 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
128 permission
: &Permission
::Privilege(&["datastore", "{name}"], PRIV_DATASTORE_ALLOCATE
, false),
131 /// Create new datastore config.
132 pub fn update_datastore(
134 comment
: Option
<String
>,
135 digest
: Option
<String
>,
136 ) -> Result
<(), Error
> {
138 let _lock
= crate::tools
::open_file_locked(datastore
::DATASTORE_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0))?
;
140 // pass/compare digest
141 let (mut config
, expected_digest
) = datastore
::config()?
;
143 if let Some(ref digest
) = digest
{
144 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
145 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
148 let mut data
: datastore
::DataStoreConfig
= config
.lookup("datastore", &name
)?
;
150 if let Some(comment
) = comment
{
151 let comment
= comment
.trim().to_string();
152 if comment
.is_empty() {
155 data
.comment
= Some(comment
);
159 config
.set_data(&name
, "datastore", &data
)?
;
161 datastore
::save_config(&config
)?
;
171 schema
: DATASTORE_SCHEMA
,
175 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
180 permission
: &Permission
::Privilege(&["datastore", "{name}"], PRIV_DATASTORE_ALLOCATE
, false),
183 /// Remove a datastore configuration.
184 pub fn delete_datastore(name
: String
, digest
: Option
<String
>) -> Result
<(), Error
> {
186 let _lock
= crate::tools
::open_file_locked(datastore
::DATASTORE_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0))?
;
188 let (mut config
, expected_digest
) = datastore
::config()?
;
190 if let Some(ref digest
) = digest
{
191 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
192 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
195 match config
.sections
.get(&name
) {
196 Some(_
) => { config.sections.remove(&name); }
,
197 None
=> bail
!("datastore '{}' does not exist.", name
),
200 datastore
::save_config(&config
)?
;
205 const ITEM_ROUTER
: Router
= Router
::new()
206 .get(&API_METHOD_READ_DATASTORE
)
207 .put(&API_METHOD_UPDATE_DATASTORE
)
208 .delete(&API_METHOD_DELETE_DATASTORE
);
210 pub const ROUTER
: Router
= Router
::new()
211 .get(&API_METHOD_LIST_DATASTORES
)
212 .post(&API_METHOD_CREATE_DATASTORE
)
213 .match_all("name", &ITEM_ROUTER
);