src/section_config.rs - convert_to_array: optionally add digest
datastore::config() -> also return digest remotes::config() -> also return digest
This commit is contained in:
		@ -485,9 +485,9 @@ fn get_datastore_list(
 | 
				
			|||||||
    _rpcenv: &mut dyn RpcEnvironment,
 | 
					    _rpcenv: &mut dyn RpcEnvironment,
 | 
				
			||||||
) -> Result<Value, Error> {
 | 
					) -> Result<Value, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let config = datastore::config()?;
 | 
					    let (config, _digest) = datastore::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(config.convert_to_array("store"))
 | 
					    Ok(config.convert_to_array("store", None))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[sortable]
 | 
					#[sortable]
 | 
				
			||||||
 | 
				
			|||||||
@ -28,9 +28,9 @@ pub fn list_datastores(
 | 
				
			|||||||
    _rpcenv: &mut dyn RpcEnvironment,
 | 
					    _rpcenv: &mut dyn RpcEnvironment,
 | 
				
			||||||
) -> Result<Value, Error> {
 | 
					) -> Result<Value, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let config = datastore::config()?;
 | 
					    let (config, digest) = datastore::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(config.convert_to_array("name"))
 | 
					    Ok(config.convert_to_array("name", Some(&digest)))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[api(
 | 
					#[api(
 | 
				
			||||||
@ -57,7 +57,7 @@ pub fn create_datastore(name: String, param: Value) -> Result<(), Error> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let datastore: datastore::DataStoreConfig = serde_json::from_value(param.clone())?;
 | 
					    let datastore: datastore::DataStoreConfig = serde_json::from_value(param.clone())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut config = datastore::config()?;
 | 
					    let (mut config, _digest) = datastore::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if let Some(_) = config.sections.get(&name) {
 | 
					    if let Some(_) = config.sections.get(&name) {
 | 
				
			||||||
        bail!("datastore '{}' already exists.", name);
 | 
					        bail!("datastore '{}' already exists.", name);
 | 
				
			||||||
@ -91,7 +91,7 @@ pub fn delete_datastore(name: String) -> Result<(), Error> {
 | 
				
			|||||||
    // fixme: locking ?
 | 
					    // fixme: locking ?
 | 
				
			||||||
    // fixme: check digest ?
 | 
					    // fixme: check digest ?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut config = datastore::config()?;
 | 
					    let (mut config, _digest) = datastore::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match config.sections.get(&name) {
 | 
					    match config.sections.get(&name) {
 | 
				
			||||||
        Some(_) => { config.sections.remove(&name); },
 | 
					        Some(_) => { config.sections.remove(&name); },
 | 
				
			||||||
 | 
				
			|||||||
@ -25,9 +25,9 @@ pub fn list_remotes(
 | 
				
			|||||||
    _rpcenv: &mut dyn RpcEnvironment,
 | 
					    _rpcenv: &mut dyn RpcEnvironment,
 | 
				
			||||||
) -> Result<Value, Error> {
 | 
					) -> Result<Value, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let config = remotes::config()?;
 | 
					    let (config, digest) = remotes::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(config.convert_to_array("name"))
 | 
					    Ok(config.convert_to_array("name", Some(&digest)))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[api(
 | 
					#[api(
 | 
				
			||||||
@ -60,7 +60,7 @@ pub fn create_remote(name: String, param: Value) -> Result<(), Error> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let remote: remotes::Remote = serde_json::from_value(param.clone())?;
 | 
					    let remote: remotes::Remote = serde_json::from_value(param.clone())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut config = remotes::config()?;
 | 
					    let (mut config, _digest) = remotes::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if let Some(_) = config.sections.get(&name) {
 | 
					    if let Some(_) = config.sections.get(&name) {
 | 
				
			||||||
        bail!("remote '{}' already exists.", name);
 | 
					        bail!("remote '{}' already exists.", name);
 | 
				
			||||||
@ -89,7 +89,7 @@ pub fn delete_remote(name: String) -> Result<(), Error> {
 | 
				
			|||||||
    // fixme: locking ?
 | 
					    // fixme: locking ?
 | 
				
			||||||
    // fixme: check digest ?
 | 
					    // fixme: check digest ?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut config = remotes::config()?;
 | 
					    let (mut config, _digest) = remotes::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match config.sections.get(&name) {
 | 
					    match config.sections.get(&name) {
 | 
				
			||||||
        Some(_) => { config.sections.remove(&name); },
 | 
					        Some(_) => { config.sections.remove(&name); },
 | 
				
			||||||
 | 
				
			|||||||
@ -35,17 +35,14 @@ impl DataStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn lookup_datastore(name: &str) -> Result<Arc<DataStore>, Error> {
 | 
					    pub fn lookup_datastore(name: &str) -> Result<Arc<DataStore>, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let config = datastore::config()?;
 | 
					        let (config, _digest) = datastore::config()?;
 | 
				
			||||||
        let (_, store_config) = config.sections.get(name)
 | 
					        let config: datastore::DataStoreConfig = config.lookup("datastore", name)?;
 | 
				
			||||||
            .ok_or(format_err!("no such datastore '{}'", name))?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let path = store_config["path"].as_str().unwrap();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut map = DATASTORE_MAP.lock().unwrap();
 | 
					        let mut map = DATASTORE_MAP.lock().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(datastore) = map.get(name) {
 | 
					        if let Some(datastore) = map.get(name) {
 | 
				
			||||||
            // Compare Config - if changed, create new Datastore object!
 | 
					            // Compare Config - if changed, create new Datastore object!
 | 
				
			||||||
            if datastore.chunk_store.base == PathBuf::from(path) {
 | 
					            if datastore.chunk_store.base == PathBuf::from(&config.path) {
 | 
				
			||||||
                return Ok(datastore.clone());
 | 
					                return Ok(datastore.clone());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -60,7 +57,7 @@ impl DataStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn open(store_name: &str) -> Result<Self, Error> {
 | 
					    pub fn open(store_name: &str) -> Result<Self, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let config = datastore::config()?;
 | 
					        let (config, _digest) = datastore::config()?;
 | 
				
			||||||
        let (_, store_config) = config.sections.get(store_name)
 | 
					        let (_, store_config) = config.sections.get(store_name)
 | 
				
			||||||
            .ok_or(format_err!("no such datastore '{}'", store_name))?;
 | 
					            .ok_or(format_err!("no such datastore '{}'", store_name))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -406,7 +406,7 @@ async fn pull_datastore(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let mut client = connect()?;
 | 
					    let mut client = connect()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let remote_config = remotes::config()?;
 | 
					    let (remote_config, _digest) = remotes::config()?;
 | 
				
			||||||
    let remote: Remote = remote_config.lookup("remote", &remote)?;
 | 
					    let remote: Remote = remote_config.lookup("remote", &remote)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let args = json!({
 | 
					    let args = json!({
 | 
				
			||||||
@ -451,7 +451,7 @@ pub fn complete_remote_datastore_name(_arg: &str, param: &HashMap<String, String
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let _ = proxmox::tools::try_block!({
 | 
					    let _ = proxmox::tools::try_block!({
 | 
				
			||||||
        let remote = param.get("remote").ok_or_else(|| format_err!("no remote"))?;
 | 
					        let remote = param.get("remote").ok_or_else(|| format_err!("no remote"))?;
 | 
				
			||||||
        let remote_config = remotes::config()?;
 | 
					        let (remote_config, _digest) = remotes::config()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let remote: Remote = remote_config.lookup("remote", &remote)?;
 | 
					        let remote: Remote = remote_config.lookup("remote", &remote)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,7 @@ fn init() -> SectionConfig {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const DATASTORE_CFG_FILENAME: &str = "/etc/proxmox-backup/datastore.cfg";
 | 
					const DATASTORE_CFG_FILENAME: &str = "/etc/proxmox-backup/datastore.cfg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn config() -> Result<SectionConfigData, Error> {
 | 
					pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
 | 
				
			||||||
    let content = match std::fs::read_to_string(DATASTORE_CFG_FILENAME) {
 | 
					    let content = match std::fs::read_to_string(DATASTORE_CFG_FILENAME) {
 | 
				
			||||||
        Ok(c) => c,
 | 
					        Ok(c) => c,
 | 
				
			||||||
        Err(err) => {
 | 
					        Err(err) => {
 | 
				
			||||||
@ -63,7 +63,9 @@ pub fn config() -> Result<SectionConfigData, Error> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CONFIG.parse(DATASTORE_CFG_FILENAME, &content)
 | 
					    let digest = openssl::sha::sha256(content.as_bytes());
 | 
				
			||||||
 | 
					    let data = CONFIG.parse(DATASTORE_CFG_FILENAME, &content)?;
 | 
				
			||||||
 | 
					    Ok((data, digest))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
 | 
					pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
 | 
				
			||||||
@ -86,7 +88,7 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
 | 
				
			|||||||
// shell completion helper
 | 
					// shell completion helper
 | 
				
			||||||
pub fn complete_datastore_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
 | 
					pub fn complete_datastore_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
 | 
				
			||||||
    match config() {
 | 
					    match config() {
 | 
				
			||||||
        Ok(data) => data.sections.iter().map(|(id, _)| id.to_string()).collect(),
 | 
					        Ok((data, _digest)) => data.sections.iter().map(|(id, _)| id.to_string()).collect(),
 | 
				
			||||||
        Err(_) => return vec![],
 | 
					        Err(_) => return vec![],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -62,7 +62,7 @@ fn init() -> SectionConfig {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const REMOTES_CFG_FILENAME: &str = "/etc/proxmox-backup/remotes.cfg";
 | 
					const REMOTES_CFG_FILENAME: &str = "/etc/proxmox-backup/remotes.cfg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn config() -> Result<SectionConfigData, Error> {
 | 
					pub fn config() -> Result<(SectionConfigData, [u8;32]), Error> {
 | 
				
			||||||
    let content = match std::fs::read_to_string(REMOTES_CFG_FILENAME) {
 | 
					    let content = match std::fs::read_to_string(REMOTES_CFG_FILENAME) {
 | 
				
			||||||
        Ok(c) => c,
 | 
					        Ok(c) => c,
 | 
				
			||||||
        Err(err) => {
 | 
					        Err(err) => {
 | 
				
			||||||
@ -74,7 +74,9 @@ pub fn config() -> Result<SectionConfigData, Error> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CONFIG.parse(REMOTES_CFG_FILENAME, &content)
 | 
					    let digest = openssl::sha::sha256(content.as_bytes());
 | 
				
			||||||
 | 
					    let data = CONFIG.parse(REMOTES_CFG_FILENAME, &content)?;
 | 
				
			||||||
 | 
					    Ok((data, digest))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
 | 
					pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
 | 
				
			||||||
@ -97,7 +99,7 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
 | 
				
			|||||||
// shell completion helper
 | 
					// shell completion helper
 | 
				
			||||||
pub fn complete_remote_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
 | 
					pub fn complete_remote_name(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
 | 
				
			||||||
    match config() {
 | 
					    match config() {
 | 
				
			||||||
        Ok(data) => data.sections.iter().map(|(id, _)| id.to_string()).collect(),
 | 
					        Ok((data, _digest)) => data.sections.iter().map(|(id, _)| id.to_string()).collect(),
 | 
				
			||||||
        Err(_) => return vec![],
 | 
					        Err(_) => return vec![],
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -84,12 +84,20 @@ impl SectionConfigData {
 | 
				
			|||||||
        self.order.push_back(section_id.to_string());
 | 
					        self.order.push_back(section_id.to_string());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn convert_to_array(&self, id_prop: &str) -> Value {
 | 
					    pub fn convert_to_array(&self, id_prop: &str, digest: Option<&[u8;32]>) -> Value {
 | 
				
			||||||
        let mut list: Vec<Value> = vec![];
 | 
					        let mut list: Vec<Value> = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let digest: Value = match digest {
 | 
				
			||||||
 | 
					            Some(v) => proxmox::tools::digest_to_hex(v).into(),
 | 
				
			||||||
 | 
					            None => Value::Null,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (section_id, (_, data)) in &self.sections {
 | 
					        for (section_id, (_, data)) in &self.sections {
 | 
				
			||||||
            let mut item = data.clone();
 | 
					            let mut item = data.clone();
 | 
				
			||||||
            item.as_object_mut().unwrap().insert(id_prop.into(), section_id.clone().into());
 | 
					            item.as_object_mut().unwrap().insert(id_prop.into(), section_id.clone().into());
 | 
				
			||||||
 | 
					            if !digest.is_null() {
 | 
				
			||||||
 | 
					                item.as_object_mut().unwrap().insert("digest".into(), digest.clone());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            list.push(item);
 | 
					            list.push(item);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user