section_config::SectionConfigData,
RpcEnvironment,
RpcEnvironmentType,
+ Permission,
Router,
SubdirMap,
},
use crate::{
task_log,
- config,
+ config::{
+ self,
+ cached_user_info::CachedUserInfo,
+ acl::{
+ PRIV_TAPE_AUDIT,
+ PRIV_TAPE_READ,
+ PRIV_TAPE_WRITE,
+ },
+ },
api2::{
types::{
UPID_SCHEMA,
open_drive,
lock_tape_device,
set_tape_device_state,
+ get_tape_device_state,
+ tape_alert_flags_critical,
},
changer::update_changer_online_status,
},
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Load media with specified label
///
},
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Load media from the specified slot
///
},
},
returns: {
- description: "The import-export slot number the media was transfered to.",
+ description: "The import-export slot number the media was transferred to.",
type: u64,
minimum: 1,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Export media with specified label
pub async fn export_media(drive: String, label_text: String) -> Result<u64, Error> {
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Unload media via changer
pub fn unload(
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_WRITE, false),
+ },
)]
/// Erase media. Check for label-text if given (cancels if wrong media).
pub fn erase_media(
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Rewind tape
pub fn rewind(
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Eject/Unload drive media
pub fn eject_media(
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_WRITE, false),
+ },
)]
/// Label media
///
},
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Try to restore a tape encryption key
pub async fn restore_key(
returns: {
type: MediaIdFlat,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Read media label (optionally inventorize media)
pub async fn read_label(
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Clean drive
pub fn clean_drive(
changer.clean_drive()?;
- worker.log("Drive cleaned sucessfully");
+ if let Ok(drive_config) = config.lookup::<LinuxTapeDrive>("linux", &drive) {
+ // Note: clean_drive unloads the cleaning media, so we cannot use drive_config.open
+ let mut handle = LinuxTapeHandle::new(open_linux_tape_device(&drive_config.path)?);
+
+ // test for critical tape alert flags
+ if let Ok(alert_flags) = handle.tape_alert_flags() {
+ if !alert_flags.is_empty() {
+ worker.log(format!("TapeAlertFlags: {:?}", alert_flags));
+ if tape_alert_flags_critical(alert_flags) {
+ bail!("found critical tape alert flags: {:?}", alert_flags);
+ }
+ }
+ }
+
+ // test wearout (max. 50 mounts)
+ if let Ok(volume_stats) = handle.volume_statistics() {
+ worker.log(format!("Volume mounts: {}", volume_stats.volume_mounts));
+ let wearout = volume_stats.volume_mounts * 2; // (*100.0/50.0);
+ worker.log(format!("Cleaning tape wearout: {}%", wearout));
+ }
+ }
+
+ worker.log("Drive cleaned successfully");
Ok(())
},
type: LabelUuidMap,
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// List known media labels (Changer Inventory)
///
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Update inventory
///
}
Ok((Some(media_id), _key_config)) => {
if label_text != media_id.label.label_text {
- worker.warn(format!("label text missmatch ({} != {})", label_text, media_id.label.label_text));
+ worker.warn(format!("label text mismatch ({} != {})", label_text, media_id.label.label_text));
continue;
}
worker.log(format!("inventorize media '{}' with uuid '{}'", label_text, media_id.label.uuid));
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_WRITE, false),
+ },
)]
/// Label media with barcodes from changer device
pub fn barcode_label_media(
) -> Result<(), Error> {
let (mut changer, changer_name) = required_media_changer(drive_config, &drive)?;
- let label_text_list = changer.online_media_label_texts()?;
+ let mut label_text_list = changer.online_media_label_texts()?;
+
+ // make sure we label them in the right order
+ label_text_list.sort();
let state_path = Path::new(TAPE_STATUS_DIR);
type: MamAttribute,
},
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_AUDIT, false),
+ },
)]
/// Read Cartridge Memory (Medium auxiliary memory attributes)
pub async fn cartridge_memory(drive: String) -> Result<Vec<MamAttribute>, Error> {
returns: {
type: Lp17VolumeStatistics,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_AUDIT, false),
+ },
)]
/// Read Volume Statistics (SCSI log page 17h)
pub async fn volume_statistics(drive: String) -> Result<Lp17VolumeStatistics, Error> {
returns: {
type: LinuxDriveAndMediaStatus,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_AUDIT, false),
+ },
)]
/// Get drive/media status
pub async fn status(drive: String) -> Result<LinuxDriveAndMediaStatus, Error> {
returns: {
schema: UPID_SCHEMA,
},
+ access: {
+ permission: &Permission::Privilege(&["tape", "device", "{drive}"], PRIV_TAPE_READ, false),
+ },
)]
/// Scan media and record content
pub fn catalog_media(
type: DriveListEntry,
},
},
+ access: {
+ description: "List configured tape drives filtered by Tape.Audit privileges",
+ permission: &Permission::Anybody,
+ },
)]
/// List drives
pub fn list_drives(
changer: Option<String>,
_param: Value,
+ rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<DriveListEntry>, Error> {
+ let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+ let user_info = CachedUserInfo::new()?;
let (config, _) = config::drive::config()?;
continue;
}
+ let privs = user_info.lookup_privs(&auth_id, &["tape", "drive", &drive.name]);
+ if (privs & PRIV_TAPE_AUDIT) == 0 {
+ continue;
+ }
+
let info = lookup_device_identification(&linux_drives, &drive.path);
- let entry = DriveListEntry { config: drive, info };
+ let state = get_tape_device_state(&config, &drive.name)?;
+ let entry = DriveListEntry { config: drive, info, state };
list.push(entry);
}