diff --git a/debian/proxmox-backup-server.install b/debian/proxmox-backup-server.install index 79757ead..ff581e3d 100644 --- a/debian/proxmox-backup-server.install +++ b/debian/proxmox-backup-server.install @@ -4,6 +4,7 @@ etc/proxmox-backup-daily-update.service /lib/systemd/system/ etc/proxmox-backup-daily-update.timer /lib/systemd/system/ etc/proxmox-backup-proxy.service /lib/systemd/system/ etc/proxmox-backup.service /lib/systemd/system/ +etc/removable-device-attach@.service /lib/systemd/system/ usr/bin/pmt usr/bin/pmtx usr/bin/proxmox-tape diff --git a/debian/proxmox-backup-server.udev b/debian/proxmox-backup-server.udev index afdfb2bc..e21b8bc7 100644 --- a/debian/proxmox-backup-server.udev +++ b/debian/proxmox-backup-server.udev @@ -16,3 +16,6 @@ SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="1", ENV{ID_SCSI_SER SYMLINK+="tape/by-id/scsi-$env{ID_SCSI_SERIAL}-sg" LABEL="persistent_storage_tape_end" + +# triggers the mounting of a removable device +ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_UUID}!="", TAG+="systemd", ENV{SYSTEMD_WANTS}="removable-device-attach@$env{ID_FS_UUID}" \ No newline at end of file diff --git a/etc/Makefile b/etc/Makefile index 42f639f6..26e91684 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -2,6 +2,7 @@ include ../defines.mk UNITS := \ proxmox-backup-daily-update.timer \ + removable-device-attach@.service DYNAMIC_UNITS := \ proxmox-backup-banner.service \ diff --git a/etc/removable-device-attach@.service b/etc/removable-device-attach@.service new file mode 100644 index 00000000..e10d1ea3 --- /dev/null +++ b/etc/removable-device-attach@.service @@ -0,0 +1,8 @@ +[Unit] +Description=Try to mount the removable device of a datastore with uuid '%i'. +After=proxmox-backup-proxy.service +Requires=proxmox-backup-proxy.service + +[Service] +Type=simple +ExecStart=/usr/sbin/proxmox-backup-manager datastore uuid-mount %i diff --git a/src/bin/proxmox_backup_manager/datastore.rs b/src/bin/proxmox_backup_manager/datastore.rs index 32a55fb9..8711997d 100644 --- a/src/bin/proxmox_backup_manager/datastore.rs +++ b/src/bin/proxmox_backup_manager/datastore.rs @@ -9,7 +9,7 @@ use proxmox_backup::api2; use proxmox_backup::api2::config::datastore::DeletableProperty; use proxmox_backup::client_helpers::connect_to_localhost; -use anyhow::Error; +use anyhow::{format_err, Error}; use serde_json::Value; #[api( @@ -244,6 +244,52 @@ async fn update_datastore(name: String, mut param: Value) -> Result<(), Error> { Ok(()) } +#[api( + protected: true, + input: { + properties: { + uuid: { + type: String, + description: "The UUID of the device that should be mounted", + }, + "output-format": { + schema: OUTPUT_FORMAT, + optional: true, + }, + }, + }, +)] +/// Try mounting a removable datastore given the UUID. +async fn uuid_mount(param: Value, _rpcenv: &mut dyn RpcEnvironment) -> Result { + let uuid = param["uuid"] + .as_str() + .ok_or_else(|| format_err!("uuid has to be specified"))?; + + let (config, _digest) = pbs_config::datastore::config()?; + let list: Vec = config.convert_to_typed_array("datastore")?; + let matching_stores: Vec = list + .into_iter() + .filter(|store: &DataStoreConfig| { + store + .backing_device + .clone() + .map_or(false, |device| device.eq(&uuid)) + }) + .collect(); + + if matching_stores.len() != 1 { + return Ok(Value::Null); + } + + if let Some(store) = matching_stores.get(0) { + api2::admin::datastore::do_mount_device(store.clone())?; + } + + // we don't want to fail for UUIDs that are not associated with datastores, as that produces + // quite some noise in the logs, given this is check for every device that is plugged in. + Ok(Value::Null) +} + pub fn datastore_commands() -> CommandLineInterface { let cmd_def = CliCommandMap::new() .insert("list", CliCommand::new(&API_METHOD_LIST_DATASTORES)) @@ -289,6 +335,10 @@ pub fn datastore_commands() -> CommandLineInterface { pbs_config::datastore::complete_calendar_event, ), ) + .insert( + "uuid-mount", + CliCommand::new(&API_METHOD_UUID_MOUNT).arg_param(&["uuid"]), + ) .insert( "remove", CliCommand::new(&API_METHOD_DELETE_DATASTORE)