]>
Commit | Line | Data |
---|---|---|
e7d4be9d DM |
1 | use anyhow::{Error}; |
2 | use lazy_static::lazy_static; | |
3 | use std::collections::HashMap; | |
4 | ||
6ef1b649 WB |
5 | use proxmox_schema::{ApiType, Schema}; |
6 | use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin}; | |
e7d4be9d DM |
7 | |
8 | use pbs_api_types::{DataStoreConfig, DATASTORE_SCHEMA}; | |
9 | ||
10 | use crate::{open_backup_lockfile, replace_backup_config, BackupLockGuard}; | |
11 | ||
12 | lazy_static! { | |
13 | pub static ref CONFIG: SectionConfig = init(); | |
14 | } | |
15 | ||
16 | fn init() -> SectionConfig { | |
17 | let obj_schema = match DataStoreConfig::API_SCHEMA { | |
18 | Schema::Object(ref obj_schema) => obj_schema, | |
19 | _ => unreachable!(), | |
20 | }; | |
21 | ||
22 | let plugin = SectionConfigPlugin::new("datastore".to_string(), Some(String::from("name")), obj_schema); | |
23 | let mut config = SectionConfig::new(&DATASTORE_SCHEMA); | |
24 | config.register_plugin(plugin); | |
25 | ||
26 | config | |
27 | } | |
28 | ||
29 | pub const DATASTORE_CFG_FILENAME: &str = "/etc/proxmox-backup/datastore.cfg"; | |
30 | pub const DATASTORE_CFG_LOCKFILE: &str = "/etc/proxmox-backup/.datastore.lck"; | |
31 | ||
32 | /// Get exclusive lock | |
33 | pub fn lock_config() -> Result<BackupLockGuard, Error> { | |
34 | open_backup_lockfile(DATASTORE_CFG_LOCKFILE, None, true) | |
35 | } | |
36 | ||
37 | pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> { | |
38 | ||
25877d05 | 39 | let content = proxmox_sys::fs::file_read_optional_string(DATASTORE_CFG_FILENAME)? |
e7d4be9d DM |
40 | .unwrap_or_else(|| "".to_string()); |
41 | ||
42 | let digest = openssl::sha::sha256(content.as_bytes()); | |
43 | let data = CONFIG.parse(DATASTORE_CFG_FILENAME, &content)?; | |
44 | Ok((data, digest)) | |
45 | } | |
46 | ||
47 | pub fn save_config(config: &SectionConfigData) -> Result<(), Error> { | |
48 | let raw = CONFIG.write(DATASTORE_CFG_FILENAME, &config)?; | |
49 | replace_backup_config(DATASTORE_CFG_FILENAME, raw.as_bytes()) | |
50 | } | |
51 | ||
52 | // shell completion helper | |
53 | pub fn complete_datastore_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> { | |
54 | match config() { | |
55 | Ok((data, _digest)) => data.sections.iter().map(|(id, _)| id.to_string()).collect(), | |
56 | Err(_) => return vec![], | |
57 | } | |
58 | } | |
59 | ||
60 | pub fn complete_acl_path(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> { | |
61 | let mut list = Vec::new(); | |
62 | ||
63 | list.push(String::from("/")); | |
64 | list.push(String::from("/datastore")); | |
65 | list.push(String::from("/datastore/")); | |
66 | ||
67 | if let Ok((data, _digest)) = config() { | |
68 | for id in data.sections.keys() { | |
69 | list.push(format!("/datastore/{}", id)); | |
70 | } | |
71 | } | |
72 | ||
73 | list.push(String::from("/remote")); | |
74 | list.push(String::from("/remote/")); | |
75 | ||
76 | list.push(String::from("/tape")); | |
77 | list.push(String::from("/tape/")); | |
78 | list.push(String::from("/tape/drive")); | |
79 | list.push(String::from("/tape/drive/")); | |
80 | list.push(String::from("/tape/changer")); | |
81 | list.push(String::from("/tape/changer/")); | |
82 | list.push(String::from("/tape/pool")); | |
83 | list.push(String::from("/tape/pool/")); | |
84 | list.push(String::from("/tape/job")); | |
85 | list.push(String::from("/tape/job/")); | |
86 | ||
87 | list | |
88 | } | |
89 | ||
90 | pub fn complete_calendar_event(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> { | |
91 | // just give some hints about possible values | |
92 | ["minutely", "hourly", "daily", "mon..fri", "0:0"] | |
93 | .iter().map(|s| String::from(*s)).collect() | |
94 | } |