mirror of
https://git.proxmox.com/git/proxmox-backup
synced 2025-08-07 01:01:42 +00:00
tape: provide 'open_lto_drive' methods for LtoTapeHandle and SgTape
Prepares for the use in sg-tape-cmd, since we want to use the SgTape directly instead of LtoTapeHandle. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
8cc8aa510f
commit
b5f8626706
@ -26,8 +26,11 @@ pub use report_density::*;
|
|||||||
use proxmox_io::{ReadExt, WriteExt};
|
use proxmox_io::{ReadExt, WriteExt};
|
||||||
use proxmox_sys::error::SysResult;
|
use proxmox_sys::error::SysResult;
|
||||||
|
|
||||||
use pbs_api_types::{Lp17VolumeStatistics, LtoDriveAndMediaStatus, MamAttribute, TapeDensity};
|
use pbs_api_types::{
|
||||||
|
Lp17VolumeStatistics, LtoDriveAndMediaStatus, LtoTapeDrive, MamAttribute, TapeDensity,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::linux_list_drives::open_lto_tape_device;
|
||||||
use crate::{
|
use crate::{
|
||||||
sgutils2::{
|
sgutils2::{
|
||||||
alloc_page_aligned_buffer, scsi_cmd_mode_select10, scsi_cmd_mode_select6, scsi_inquiry,
|
alloc_page_aligned_buffer, scsi_cmd_mode_select10, scsi_cmd_mode_select6, scsi_inquiry,
|
||||||
@ -129,6 +132,43 @@ impl SgTape {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Open a tape device
|
||||||
|
///
|
||||||
|
/// This does additional checks:
|
||||||
|
///
|
||||||
|
/// - check if it is a non-rewinding tape device
|
||||||
|
/// - check if drive is ready (tape loaded)
|
||||||
|
/// - check block size
|
||||||
|
/// - for autoloader only, try to reload ejected tapes
|
||||||
|
pub fn open_lto_drive(config: &LtoTapeDrive) -> Result<Self, Error> {
|
||||||
|
proxmox_lang::try_block!({
|
||||||
|
let file = open_lto_tape_device(&config.path)?;
|
||||||
|
|
||||||
|
let mut handle = SgTape::new(file)?;
|
||||||
|
|
||||||
|
if handle.test_unit_ready().is_err() {
|
||||||
|
// for autoloader only, try to reload ejected tapes
|
||||||
|
if config.changer.is_some() {
|
||||||
|
let _ = handle.load(); // just try, ignore error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.wait_until_ready(None)?;
|
||||||
|
|
||||||
|
handle.set_default_options()?;
|
||||||
|
|
||||||
|
Ok(handle)
|
||||||
|
})
|
||||||
|
.map_err(|err: Error| {
|
||||||
|
format_err!(
|
||||||
|
"open drive '{}' ({}) failed - {}",
|
||||||
|
config.name,
|
||||||
|
config.path,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Access to file descriptor - useful for testing
|
/// Access to file descriptor - useful for testing
|
||||||
pub fn file_mut(&mut self) -> &mut File {
|
pub fn file_mut(&mut self) -> &mut File {
|
||||||
&mut self.file
|
&mut self.file
|
||||||
|
@ -36,8 +36,7 @@ use crate::{
|
|||||||
changer::update_changer_online_status,
|
changer::update_changer_online_status,
|
||||||
drive::{
|
drive::{
|
||||||
get_tape_device_state, lock_tape_device, media_changer, open_drive,
|
get_tape_device_state, lock_tape_device, media_changer, open_drive,
|
||||||
open_lto_tape_drive, required_media_changer, set_tape_device_state, LtoTapeHandle,
|
required_media_changer, set_tape_device_state, LtoTapeHandle, TapeDriver,
|
||||||
TapeDriver,
|
|
||||||
},
|
},
|
||||||
encryption_keys::insert_key,
|
encryption_keys::insert_key,
|
||||||
file_formats::{MediaLabel, MediaSetLabel},
|
file_formats::{MediaLabel, MediaSetLabel},
|
||||||
@ -1192,7 +1191,7 @@ pub async fn cartridge_memory(drive: String) -> Result<Vec<MamAttribute>, Error>
|
|||||||
"reading cartridge memory".to_string(),
|
"reading cartridge memory".to_string(),
|
||||||
move |config| {
|
move |config| {
|
||||||
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
||||||
let mut handle = open_lto_tape_drive(&drive_config)?;
|
let mut handle = LtoTapeHandle::open_lto_drive(&drive_config)?;
|
||||||
|
|
||||||
handle.cartridge_memory()
|
handle.cartridge_memory()
|
||||||
},
|
},
|
||||||
@ -1222,7 +1221,7 @@ pub async fn volume_statistics(drive: String) -> Result<Lp17VolumeStatistics, Er
|
|||||||
"reading volume statistics".to_string(),
|
"reading volume statistics".to_string(),
|
||||||
move |config| {
|
move |config| {
|
||||||
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
let drive_config: LtoTapeDrive = config.lookup("lto", &drive)?;
|
||||||
let mut handle = open_lto_tape_drive(&drive_config)?;
|
let mut handle = LtoTapeHandle::open_lto_drive(&drive_config)?;
|
||||||
|
|
||||||
handle.volume_statistics()
|
handle.volume_statistics()
|
||||||
},
|
},
|
||||||
|
@ -19,14 +19,14 @@ use pbs_api_types::{
|
|||||||
|
|
||||||
use pbs_tape::linux_list_drives::{check_tape_is_lto_tape_device, open_lto_tape_device};
|
use pbs_tape::linux_list_drives::{check_tape_is_lto_tape_device, open_lto_tape_device};
|
||||||
|
|
||||||
use proxmox_backup::tape::drive::{open_lto_tape_drive, LtoTapeHandle, TapeDriver};
|
use proxmox_backup::tape::drive::{LtoTapeHandle, TapeDriver};
|
||||||
|
|
||||||
fn get_tape_handle(param: &Value) -> Result<LtoTapeHandle, Error> {
|
fn get_tape_handle(param: &Value) -> Result<LtoTapeHandle, Error> {
|
||||||
let handle = if let Some(name) = param["drive"].as_str() {
|
let handle = if let Some(name) = param["drive"].as_str() {
|
||||||
let (config, _digest) = pbs_config::drive::config()?;
|
let (config, _digest) = pbs_config::drive::config()?;
|
||||||
let drive: LtoTapeDrive = config.lookup("lto", name)?;
|
let drive: LtoTapeDrive = config.lookup("lto", name)?;
|
||||||
log::info!("using device {}", drive.path);
|
log::info!("using device {}", drive.path);
|
||||||
open_lto_tape_drive(&drive)?
|
LtoTapeHandle::open_lto_drive(&drive)?
|
||||||
} else if let Some(device) = param["device"].as_str() {
|
} else if let Some(device) = param["device"].as_str() {
|
||||||
log::info!("using device {}", device);
|
log::info!("using device {}", device);
|
||||||
LtoTapeHandle::new(open_lto_tape_device(device)?)?
|
LtoTapeHandle::new(open_lto_tape_device(device)?)?
|
||||||
@ -40,7 +40,7 @@ fn get_tape_handle(param: &Value) -> Result<LtoTapeHandle, Error> {
|
|||||||
let (config, _digest) = pbs_config::drive::config()?;
|
let (config, _digest) = pbs_config::drive::config()?;
|
||||||
let drive: LtoTapeDrive = config.lookup("lto", &name)?;
|
let drive: LtoTapeDrive = config.lookup("lto", &name)?;
|
||||||
log::info!("using device {}", drive.path);
|
log::info!("using device {}", drive.path);
|
||||||
open_lto_tape_drive(&drive)?
|
LtoTapeHandle::open_lto_drive(&drive)?
|
||||||
} else {
|
} else {
|
||||||
let (config, _digest) = pbs_config::drive::config()?;
|
let (config, _digest) = pbs_config::drive::config()?;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ fn get_tape_handle(param: &Value) -> Result<LtoTapeHandle, Error> {
|
|||||||
let name = drive_names[0];
|
let name = drive_names[0];
|
||||||
let drive: LtoTapeDrive = config.lookup("lto", name)?;
|
let drive: LtoTapeDrive = config.lookup("lto", name)?;
|
||||||
log::info!("using device {}", drive.path);
|
log::info!("using device {}", drive.path);
|
||||||
open_lto_tape_drive(&drive)?
|
LtoTapeHandle::open_lto_drive(&drive)?
|
||||||
} else {
|
} else {
|
||||||
bail!("no drive/device specified");
|
bail!("no drive/device specified");
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ use pbs_api_types::{
|
|||||||
};
|
};
|
||||||
use pbs_key_config::KeyConfig;
|
use pbs_key_config::KeyConfig;
|
||||||
use pbs_tape::{
|
use pbs_tape::{
|
||||||
linux_list_drives::open_lto_tape_device,
|
|
||||||
sg_tape::{SgTape, TapeAlertFlags},
|
sg_tape::{SgTape, TapeAlertFlags},
|
||||||
BlockReadError, MediaContentHeader, TapeRead, TapeWrite,
|
BlockReadError, MediaContentHeader, TapeRead, TapeWrite,
|
||||||
};
|
};
|
||||||
@ -34,43 +33,6 @@ use crate::tape::{
|
|||||||
file_formats::{MediaSetLabel, PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0},
|
file_formats::{MediaSetLabel, PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Open a tape device
|
|
||||||
///
|
|
||||||
/// This does additional checks:
|
|
||||||
///
|
|
||||||
/// - check if it is a non-rewinding tape device
|
|
||||||
/// - check if drive is ready (tape loaded)
|
|
||||||
/// - check block size
|
|
||||||
/// - for autoloader only, try to reload ejected tapes
|
|
||||||
pub fn open_lto_tape_drive(config: &LtoTapeDrive) -> Result<LtoTapeHandle, Error> {
|
|
||||||
proxmox_lang::try_block!({
|
|
||||||
let file = open_lto_tape_device(&config.path)?;
|
|
||||||
|
|
||||||
let mut handle = LtoTapeHandle::new(file)?;
|
|
||||||
|
|
||||||
if handle.sg_tape.test_unit_ready().is_err() {
|
|
||||||
// for autoloader only, try to reload ejected tapes
|
|
||||||
if config.changer.is_some() {
|
|
||||||
let _ = handle.sg_tape.load(); // just try, ignore error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle.sg_tape.wait_until_ready(None)?;
|
|
||||||
|
|
||||||
handle.set_default_options()?;
|
|
||||||
|
|
||||||
Ok(handle)
|
|
||||||
})
|
|
||||||
.map_err(|err: Error| {
|
|
||||||
format_err!(
|
|
||||||
"open drive '{}' ({}) failed - {}",
|
|
||||||
config.name,
|
|
||||||
config.path,
|
|
||||||
err
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lto Tape device handle
|
/// Lto Tape device handle
|
||||||
pub struct LtoTapeHandle {
|
pub struct LtoTapeHandle {
|
||||||
sg_tape: SgTape,
|
sg_tape: SgTape,
|
||||||
@ -83,6 +45,18 @@ impl LtoTapeHandle {
|
|||||||
Ok(Self { sg_tape })
|
Ok(Self { sg_tape })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Open a tape device
|
||||||
|
///
|
||||||
|
/// since this calls [SgTape::open_lto_drive], it does some internal checks.
|
||||||
|
/// See [SgTape] docs for details.
|
||||||
|
pub fn open_lto_drive(config: &LtoTapeDrive) -> Result<Self, Error> {
|
||||||
|
let sg_tape = SgTape::open_lto_drive(config)?;
|
||||||
|
|
||||||
|
let handle = Self { sg_tape };
|
||||||
|
|
||||||
|
Ok(handle)
|
||||||
|
}
|
||||||
|
|
||||||
/// Set all options we need/want
|
/// Set all options we need/want
|
||||||
pub fn set_default_options(&mut self) -> Result<(), Error> {
|
pub fn set_default_options(&mut self) -> Result<(), Error> {
|
||||||
self.sg_tape.set_default_options()?;
|
self.sg_tape.set_default_options()?;
|
||||||
|
@ -280,7 +280,7 @@ pub fn open_drive(config: &SectionConfigData, drive: &str) -> Result<Box<dyn Tap
|
|||||||
}
|
}
|
||||||
"lto" => {
|
"lto" => {
|
||||||
let tape = LtoTapeDrive::deserialize(config)?;
|
let tape = LtoTapeDrive::deserialize(config)?;
|
||||||
let handle = open_lto_tape_drive(&tape)?;
|
let handle = LtoTapeHandle::open_lto_drive(&tape)?;
|
||||||
Ok(Box::new(handle))
|
Ok(Box::new(handle))
|
||||||
}
|
}
|
||||||
ty => bail!("unknown drive type '{}' - internal error", ty),
|
ty => bail!("unknown drive type '{}' - internal error", ty),
|
||||||
@ -449,7 +449,7 @@ pub fn request_and_load_media(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut handle = match open_lto_tape_drive(&drive_config) {
|
let mut handle = match LtoTapeHandle::open_lto_drive(&drive_config) {
|
||||||
Ok(handle) => handle,
|
Ok(handle) => handle,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
update_and_log_request_error(
|
update_and_log_request_error(
|
||||||
|
Loading…
Reference in New Issue
Block a user