tape: improve media request/load

This commit is contained in:
Dietmar Maurer 2020-12-30 12:58:06 +01:00
parent 2fb1bdda20
commit ff58c51919
4 changed files with 76 additions and 26 deletions

View File

@ -178,7 +178,7 @@ pub fn backup_snapshot(
break; break;
} }
let uuid = pool_writer.load_writable_media()?; let uuid = pool_writer.load_writable_media(worker)?;
let (leom, _bytes) = pool_writer.append_chunk_archive(&datastore, &mut chunk_iter)?; let (leom, _bytes) = pool_writer.append_chunk_archive(&datastore, &mut chunk_iter)?;
@ -187,7 +187,7 @@ pub fn backup_snapshot(
} }
} }
let uuid = pool_writer.load_writable_media()?; let uuid = pool_writer.load_writable_media(worker)?;
let (done, _bytes) = pool_writer.append_snapshot_archive(&snapshot_reader)?; let (done, _bytes) = pool_writer.append_snapshot_archive(&snapshot_reader)?;
@ -195,7 +195,7 @@ pub fn backup_snapshot(
// does not fit on tape, so we try on next volume // does not fit on tape, so we try on next volume
pool_writer.set_media_status_full(&uuid)?; pool_writer.set_media_status_full(&uuid)?;
pool_writer.load_writable_media()?; pool_writer.load_writable_media(worker)?;
let (done, _bytes) = pool_writer.append_snapshot_archive(&snapshot_reader)?; let (done, _bytes) = pool_writer.append_snapshot_archive(&snapshot_reader)?;
if !done { if !done {

View File

@ -67,7 +67,7 @@ pub fn request_and_restore_media(
Some(ref set) => &set.uuid, Some(ref set) => &set.uuid,
}; };
let (mut drive, info) = request_and_load_media(&drive_config, &drive_name, &media_id.label)?; let (mut drive, info) = request_and_load_media(worker, &drive_config, &drive_name, &media_id.label)?;
match info.media_set_label { match info.media_set_label {
None => { None => {

View File

@ -19,6 +19,7 @@ use crate::{
VirtualTapeDrive, VirtualTapeDrive,
LinuxTapeDrive, LinuxTapeDrive,
}, },
server::WorkerTask,
tape::{ tape::{
TapeWrite, TapeWrite,
TapeRead, TapeRead,
@ -223,6 +224,7 @@ pub fn open_drive(
/// ///
/// Returns a handle to the opened drive and the media labels. /// Returns a handle to the opened drive and the media labels.
pub fn request_and_load_media( pub fn request_and_load_media(
worker: &WorkerTask,
config: &SectionConfigData, config: &SectionConfigData,
drive: &str, drive: &str,
label: &MediaLabel, label: &MediaLabel,
@ -231,51 +233,97 @@ pub fn request_and_load_media(
MediaId, MediaId,
), Error> { ), Error> {
let check_label = |handle: &mut dyn TapeDriver, uuid: &proxmox::tools::Uuid| {
if let Ok(Some(media_id)) = handle.read_label() {
println!("found media label {} ({})", media_id.label.changer_id, media_id.label.uuid.to_string());
if media_id.label.uuid == *uuid {
return Ok(media_id);
}
}
bail!("read label failed (please label all tapes first)");
};
match config.sections.get(drive) { match config.sections.get(drive) {
Some((section_type_name, config)) => { Some((section_type_name, config)) => {
match section_type_name.as_ref() { match section_type_name.as_ref() {
"virtual" => { "virtual" => {
let mut drive = VirtualTapeDrive::deserialize(config)?; let mut tape = VirtualTapeDrive::deserialize(config)?;
let changer_id = label.changer_id.clone(); let changer_id = label.changer_id.clone();
drive.load_media(&changer_id)?; tape.load_media(&changer_id)?;
let mut handle = drive.open()?; let mut handle: Box<dyn TapeDriver> = Box::new(tape.open()?);
if let Ok(Some(media_id)) = handle.read_label() { let media_id = check_label(handle.as_mut(), &label.uuid)?;
println!("found media label {} ({})", media_id.label.changer_id, media_id.label.uuid.to_string());
if media_id.label.uuid == label.uuid { return Ok((handle, media_id));
return Ok((Box::new(handle), media_id));
}
}
bail!("read label failed (label all tapes first)");
} }
"linux" => { "linux" => {
let tape = LinuxTapeDrive::deserialize(config)?; let mut tape = LinuxTapeDrive::deserialize(config)?;
let id = label.changer_id.clone(); let changer_id = label.changer_id.clone();
println!("Please insert media '{}' into drive '{}'", id, drive); if tape.changer.is_some() {
tape.load_media(&changer_id)?;
let mut handle: Box<dyn TapeDriver> = Box::new(tape.open()?);
let media_id = check_label(handle.as_mut(), &label.uuid)?;
return Ok((handle, media_id));
}
worker.log(format!("Please insert media '{}' into drive '{}'", changer_id, drive));
let to = "root@localhost"; // fixme
let mut changer = ChangeMediaEmail::new(drive, to);
changer.load_media(&changer_id)?; // semd email
let mut last_media_uuid = None;
loop { loop {
let mut handle = match tape.open() { let mut handle = match tape.open() {
Ok(handle) => handle, Ok(handle) => handle,
Err(_) => { Err(_) => {
eprintln!("tape open failed - test again in 5 secs"); //eprintln!("tape open failed - test again in 5 secs");
std::thread::sleep(std::time::Duration::from_millis(5_000)); std::thread::sleep(std::time::Duration::from_millis(5_000));
continue; continue;
} }
}; };
if let Ok(Some(media_id)) = handle.read_label() { match handle.read_label() {
println!("found media label {} ({})", media_id.label.changer_id, media_id.label.uuid.to_string()); Ok(Some(media_id)) => {
if media_id.label.uuid == label.uuid { if media_id.label.uuid == label.uuid {
worker.log(format!(
"found media label {} ({})",
media_id.label.changer_id,
media_id.label.uuid.to_string(),
));
return Ok((Box::new(handle), media_id)); return Ok((Box::new(handle), media_id));
} else {
if Some(media_id.label.uuid.clone()) != last_media_uuid {
worker.log(format!(
"wrong media label {} ({})",
media_id.label.changer_id,
media_id.label.uuid.to_string(),
));
last_media_uuid = Some(media_id.label.uuid);
} }
} }
}
Ok(None) => {
if last_media_uuid.is_some() {
worker.log(format!("found empty media without label (please label all tapes first)"));
last_media_uuid = None;
}
}
Err(_) => { /* test again */ }
}
println!("read label failed - test again in 5 secs"); // eprintln!("read label failed - test again in 5 secs");
std::thread::sleep(std::time::Duration::from_millis(5_000)); std::thread::sleep(std::time::Duration::from_millis(5_000));
} }
} }

View File

@ -12,6 +12,7 @@ use crate::{
backup::{ backup::{
DataStore, DataStore,
}, },
server::WorkerTask,
tape::{ tape::{
TAPE_STATUS_DIR, TAPE_STATUS_DIR,
MAX_CHUNK_ARCHIVE_SIZE, MAX_CHUNK_ARCHIVE_SIZE,
@ -118,7 +119,7 @@ impl PoolWriter {
} }
/// Load a writable media into the drive /// Load a writable media into the drive
pub fn load_writable_media(&mut self) -> Result<Uuid, Error> { pub fn load_writable_media(&mut self, worker: &WorkerTask) -> Result<Uuid, Error> {
let last_media_uuid = match self.status { let last_media_uuid = match self.status {
Some(PoolWriterState { ref catalog, .. }) => Some(catalog.uuid().clone()), Some(PoolWriterState { ref catalog, .. }) => Some(catalog.uuid().clone()),
None => None, None => None,
@ -147,7 +148,7 @@ impl PoolWriter {
} }
let (drive_config, _digest) = crate::config::drive::config()?; let (drive_config, _digest) = crate::config::drive::config()?;
let (drive, catalog) = drive_load_and_label_media(&drive_config, &self.drive_name, &media.id())?; let (drive, catalog) = drive_load_and_label_media(worker, &drive_config, &self.drive_name, &media.id())?;
self.status = Some(PoolWriterState { drive, catalog, at_eom: false, bytes_written: 0 }); self.status = Some(PoolWriterState { drive, catalog, at_eom: false, bytes_written: 0 });
Ok(media_uuid) Ok(media_uuid)
@ -333,13 +334,14 @@ fn write_chunk_archive<'a>(
// set label. If the tabe is empty, or the existing set label does not // set label. If the tabe is empty, or the existing set label does not
// match the expected media set, overwrite the media set label. // match the expected media set, overwrite the media set label.
fn drive_load_and_label_media( fn drive_load_and_label_media(
worker: &WorkerTask,
drive_config: &SectionConfigData, drive_config: &SectionConfigData,
drive_name: &str, drive_name: &str,
media_id: &MediaId, media_id: &MediaId,
) -> Result<(Box<dyn TapeDriver>, MediaCatalog), Error> { ) -> Result<(Box<dyn TapeDriver>, MediaCatalog), Error> {
let (mut tmp_drive, info) = let (mut tmp_drive, info) =
request_and_load_media(&drive_config, &drive_name, &media_id.label)?; request_and_load_media(worker, &drive_config, &drive_name, &media_id.label)?;
let media_catalog; let media_catalog;