[pbs-devel] [PATCH proxmox-backup v3 1/2] api2/node/../disks/directory: added DELETE endpoint for removal of mount-units
Hannes Laimer
h.laimer at proxmox.com
Thu Aug 13 12:58:52 CEST 2020
Signed-off-by: Hannes Laimer <h.laimer at proxmox.com>
---
src/api2/node/disks/directory.rs | 72 +++++++++++++++++++++++++++++++-
src/tools/systemd.rs | 11 +++++
2 files changed, 81 insertions(+), 2 deletions(-)
diff --git a/src/api2/node/disks/directory.rs b/src/api2/node/disks/directory.rs
index f05b781f..f8a8d8cb 100644
--- a/src/api2/node/disks/directory.rs
+++ b/src/api2/node/disks/directory.rs
@@ -2,7 +2,7 @@ use anyhow::{bail, Error};
use serde_json::json;
use ::serde::{Deserialize, Serialize};
-use proxmox::api::{api, Permission, RpcEnvironment, RpcEnvironmentType};
+use proxmox::api::{api, Permission, RpcEnvironment, RpcEnvironmentType, HttpError};
use proxmox::api::section_config::SectionConfigData;
use proxmox::api::router::Router;
@@ -16,6 +16,8 @@ use crate::tools::systemd::{self, types::*};
use crate::server::WorkerTask;
use crate::api2::types::*;
+use proxmox::api::error::StatusCode;
+use crate::config::datastore::DataStoreConfig;
#[api(
properties: {
@@ -175,9 +177,75 @@ pub fn create_datastore_disk(
Ok(upid_str)
}
+#[api(
+ protected: true,
+ input: {
+ properties: {
+ node: {
+ schema: NODE_SCHEMA,
+ },
+ name: {
+ schema: DATASTORE_SCHEMA,
+ },
+ }
+ },
+ access: {
+ permission: &Permission::Privilege(&["system", "disks"], PRIV_SYS_MODIFY, false),
+ },
+)]
+/// Remove a Filesystem mounted under '/mnt/datastore/<name>'.".
+pub fn delete_datastore_disk(
+ name: String,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let path = format!("/mnt/datastore/{}", name);
+ // path of datastore cannot be changed
+ let (config, _) = crate::config::datastore::config()?;
+ let datastores: Vec<DataStoreConfig> = config.convert_to_typed_array("datastore")?;
+ let conflicting_datastore: Option<DataStoreConfig> = datastores.into_iter()
+ .filter(|ds| ds.path == path)
+ .next();
+
+ match conflicting_datastore {
+ Some(conflicting_datastore) =>
+ Err(Error::from(HttpError::new(StatusCode::CONFLICT,
+ format!("Can't remove '{}' since it's required by datastore '{}'",
+ conflicting_datastore.path,
+ conflicting_datastore.name)))),
+ None => {
+ // disable systemd mount-unit
+ let mut mount_unit_name = systemd::escape_unit(&path, true);
+ mount_unit_name.push_str(".mount");
+ systemd::disable_unit(mount_unit_name.as_str())?;
+
+ // delete .mount-file
+ let mount_unit_path = format!("/etc/systemd/system/{}", mount_unit_name);
+ let full_path = std::path::Path::new(mount_unit_path.as_str());
+ log::info!("removing {:?}", full_path);
+ std::fs::remove_file(&full_path)?;
+
+ // try to unmount, if that fails tell the user to reboot or unmount manually
+ let mut command = std::process::Command::new("umount");
+ command.arg(path.as_str());
+ match crate::tools::run_command(command, None) {
+ Err(_) => bail!(
+ "Could not umount '{}' since it is busy. It will stay mounted \
+ until the next reboot or until unmounted manually!",
+ path
+ ),
+ Ok(_) => Ok(())
+ }
+ }
+ }
+}
+
+const ITEM_ROUTER: Router = Router::new()
+ .delete(&API_METHOD_DELETE_DATASTORE_DISK);
+
pub const ROUTER: Router = Router::new()
.get(&API_METHOD_LIST_DATASTORE_MOUNTS)
- .post(&API_METHOD_CREATE_DATASTORE_DISK);
+ .post(&API_METHOD_CREATE_DATASTORE_DISK)
+ .match_all("name", &ITEM_ROUTER);
fn create_datastore_mount_unit(
diff --git a/src/tools/systemd.rs b/src/tools/systemd.rs
index 6dde06a3..9a6439de 100644
--- a/src/tools/systemd.rs
+++ b/src/tools/systemd.rs
@@ -83,6 +83,17 @@ pub fn reload_daemon() -> Result<(), Error> {
Ok(())
}
+pub fn disable_unit(unit: &str) -> Result<(), Error> {
+
+ let mut command = std::process::Command::new("systemctl");
+ command.arg("disable");
+ command.arg(unit);
+
+ crate::tools::run_command(command, None)?;
+
+ Ok(())
+}
+
pub fn enable_unit(unit: &str) -> Result<(), Error> {
let mut command = std::process::Command::new("systemctl");
--
2.20.1
More information about the pbs-devel
mailing list