+use ::serde::{Deserialize, Serialize};
use anyhow::{bail, Error};
use serde_json::json;
-use ::serde::{Deserialize, Serialize};
-use proxmox::api::{api, Permission, RpcEnvironment, RpcEnvironmentType};
-use proxmox::api::section_config::SectionConfigData;
-use proxmox::api::router::Router;
+use proxmox_router::{Permission, Router, RpcEnvironment, RpcEnvironmentType};
+use proxmox_schema::api;
+use proxmox_section_config::SectionConfigData;
+use proxmox_sys::task_log;
+
+use pbs_api_types::{
+ DataStoreConfig, BLOCKDEVICE_NAME_SCHEMA, DATASTORE_SCHEMA, NODE_SCHEMA, PRIV_SYS_AUDIT,
+ PRIV_SYS_MODIFY, UPID_SCHEMA,
+};
-use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
use crate::tools::disks::{
- DiskManage, FileSystemType, DiskUsageType,
- create_file_system, create_single_linux_partition, get_fs_uuid, get_disk_usage_info,
+ create_file_system, create_single_linux_partition, get_fs_uuid, DiskManage, DiskUsageQuery,
+ DiskUsageType, FileSystemType,
};
use crate::tools::systemd::{self, types::*};
-use crate::server::WorkerTask;
+use proxmox_rest_server::WorkerTask;
-use crate::api2::types::*;
-use crate::config::datastore::{self, DataStoreConfig};
-use crate::backup::open_backup_lockfile;
+const BASE_MOUNT_DIR: &str = "/mnt/datastore/";
#[api(
properties: {
},
)]
#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all="kebab-case")]
+#[serde(rename_all = "kebab-case")]
/// Datastore mount info.
pub struct DatastoreMountInfo {
/// The path of the mount unit.
pub unitfile: String,
+ /// The name of the mount
+ pub name: String,
/// The mount path.
pub path: String,
/// The mounted device.
},
)]
/// List systemd datastore mount units.
-pub fn list_datastore_mounts() -> Result<Vec<DatastoreMountInfo>, Error> {
-
+pub fn list_datastore_mounts() -> Result<Vec<DatastoreMountInfo>, Error> {
lazy_static::lazy_static! {
static ref MOUNT_NAME_REGEX: regex::Regex = regex::Regex::new(r"^mnt-datastore-(.+)\.mount$").unwrap();
}
let mut list = Vec::new();
let basedir = "/etc/systemd/system";
- for item in pbs_tools::fs::scan_subdir(libc::AT_FDCWD, basedir, &MOUNT_NAME_REGEX)? {
+ for item in proxmox_sys::fs::scan_subdir(libc::AT_FDCWD, basedir, &MOUNT_NAME_REGEX)? {
let item = item?;
let name = item.file_name().to_string_lossy().to_string();
let config = systemd::config::parse_systemd_mount(&unitfile)?;
let data: SystemdMountSection = config.lookup("Mount", "Mount")?;
+ let name = data
+ .Where
+ .strip_prefix(BASE_MOUNT_DIR)
+ .unwrap_or_else(|| &data.Where)
+ .to_string();
+
list.push(DatastoreMountInfo {
unitfile,
+ name,
device: data.What,
path: data.Where,
filesystem: data.Type,
filesystem: Option<FileSystemType>,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<String, Error> {
-
let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
- let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+ let auth_id = rpcenv.get_auth_id().unwrap();
- let info = get_disk_usage_info(&disk, true)?;
+ let info = DiskUsageQuery::new().smart(false).find(&disk)?;
if info.used != DiskUsageType::Unused {
bail!("disk '{}' is already in use.", disk);
}
- let mount_point = format!("/mnt/datastore/{}", &name);
+ let mount_point = format!("{}{}", BASE_MOUNT_DIR, &name);
// check if the default path does exist already and bail if it does
let default_path = std::path::PathBuf::from(&mount_point);
match std::fs::metadata(&default_path) {
- Err(_) => {}, // path does not exist
+ Err(_) => {} // path does not exist
Ok(_) => {
bail!("path {:?} already exists", default_path);
}
}
let upid_str = WorkerTask::new_thread(
- "dircreate", Some(name.clone()), auth_id, to_stdout, move |worker|
- {
- worker.log(format!("create datastore '{}' on disk {}", name, disk));
+ "dircreate",
+ Some(name.clone()),
+ auth_id,
+ to_stdout,
+ move |worker| {
+ task_log!(worker, "create datastore '{}' on disk {}", name, disk);
let add_datastore = add_datastore.unwrap_or(false);
let filesystem = filesystem.unwrap_or(FileSystemType::Ext4);
let uuid = get_fs_uuid(&partition)?;
let uuid_path = format!("/dev/disk/by-uuid/{}", uuid);
- let mount_unit_name = create_datastore_mount_unit(&name, &mount_point, filesystem, &uuid_path)?;
+ let mount_unit_name =
+ create_datastore_mount_unit(&name, &mount_point, filesystem, &uuid_path)?;
- systemd::reload_daemon()?;
- systemd::enable_unit(&mount_unit_name)?;
- systemd::start_unit(&mount_unit_name)?;
+ crate::tools::systemd::reload_daemon()?;
+ crate::tools::systemd::enable_unit(&mount_unit_name)?;
+ crate::tools::systemd::start_unit(&mount_unit_name)?;
if add_datastore {
- let lock = open_backup_lockfile(datastore::DATASTORE_CFG_LOCKFILE, None, true)?;
+ let lock = pbs_config::datastore::lock_config()?;
let datastore: DataStoreConfig =
serde_json::from_value(json!({ "name": name, "path": mount_point }))?;
- let (config, _digest) = datastore::config()?;
+ let (config, _digest) = pbs_config::datastore::config()?;
if config.sections.get(&datastore.name).is_some() {
bail!("datastore '{}' already exists.", datastore.name);
}
- crate::api2::config::datastore::do_create_datastore(lock, config, datastore, Some(&worker))?;
+ crate::api2::config::datastore::do_create_datastore(
+ lock,
+ config,
+ datastore,
+ Some(&worker),
+ )?;
}
Ok(())
- })?;
+ },
+ )?;
Ok(upid_str)
}
)]
/// Remove a Filesystem mounted under '/mnt/datastore/<name>'.".
pub fn delete_datastore_disk(name: String) -> Result<(), Error> {
-
- let path = format!("/mnt/datastore/{}", name);
+ let path = format!("{}{}", BASE_MOUNT_DIR, name);
// path of datastore cannot be changed
- let (config, _) = crate::config::datastore::config()?;
+ let (config, _) = pbs_config::datastore::config()?;
let datastores: Vec<DataStoreConfig> = config.convert_to_typed_array("datastore")?;
- let conflicting_datastore: Option<DataStoreConfig> = datastores.into_iter()
- .find(|ds| ds.path == path);
+ let conflicting_datastore: Option<DataStoreConfig> =
+ datastores.into_iter().find(|ds| ds.path == path);
if let Some(conflicting_datastore) = conflicting_datastore {
- bail!("Can't remove '{}' since it's required by datastore '{}'",
- conflicting_datastore.path, conflicting_datastore.name);
+ bail!(
+ "Can't remove '{}' since it's required by datastore '{}'",
+ conflicting_datastore.path,
+ conflicting_datastore.name
+ );
}
// disable systemd mount-unit
- let mut mount_unit_name = systemd::escape_unit(&path, true);
+ let mut mount_unit_name = proxmox_sys::systemd::escape_unit(&path, true);
mount_unit_name.push_str(".mount");
- systemd::disable_unit(&mount_unit_name)?;
+ crate::tools::systemd::disable_unit(&mount_unit_name)?;
// delete .mount-file
let mount_unit_path = format!("/etc/systemd/system/{}", mount_unit_name);
// 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);
- match crate::tools::run_command(command, None) {
+ match proxmox_sys::command::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(())
+ Ok(_) => Ok(()),
}
}
-const ITEM_ROUTER: Router = Router::new()
- .delete(&API_METHOD_DELETE_DATASTORE_DISK);
+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)
.match_all("name", &ITEM_ROUTER);
-
fn create_datastore_mount_unit(
datastore_name: &str,
mount_point: &str,
fs_type: FileSystemType,
what: &str,
) -> Result<String, Error> {
-
- let mut mount_unit_name = systemd::escape_unit(&mount_point, true);
+ let mut mount_unit_name = proxmox_sys::systemd::escape_unit(mount_point, true);
mount_unit_name.push_str(".mount");
let mount_unit_path = format!("/etc/systemd/system/{}", mount_unit_name);
let unit = SystemdUnitSection {
- Description: format!("Mount datatstore '{}' under '{}'", datastore_name, mount_point),
+ Description: format!(
+ "Mount datatstore '{}' under '{}'",
+ datastore_name, mount_point
+ ),
..Default::default()
};