tape: improve media request/load
This commit is contained in:
parent
2fb1bdda20
commit
ff58c51919
@ -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 {
|
||||||
|
@ -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 => {
|
||||||
|
@ -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 {
|
||||||
return Ok((Box::new(handle), media_id));
|
worker.log(format!(
|
||||||
|
"found media label {} ({})",
|
||||||
|
media_id.label.changer_id,
|
||||||
|
media_id.label.uuid.to_string(),
|
||||||
|
));
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user