tape: remove MediaLabelInfo, use MediaId instead
The additional content_uuid was quite useless...
This commit is contained in:
parent
42150d263b
commit
fe6c19383b
|
@ -32,7 +32,7 @@ use crate::{
|
||||||
LinuxTapeDrive,
|
LinuxTapeDrive,
|
||||||
ScsiTapeChanger,
|
ScsiTapeChanger,
|
||||||
TapeDeviceInfo,
|
TapeDeviceInfo,
|
||||||
MediaLabelInfoFlat,
|
MediaIdFlat,
|
||||||
LabelUuidMap,
|
LabelUuidMap,
|
||||||
},
|
},
|
||||||
server::WorkerTask,
|
server::WorkerTask,
|
||||||
|
@ -405,7 +405,7 @@ fn write_media_label(
|
||||||
}
|
}
|
||||||
if let Some(ref pool) = pool {
|
if let Some(ref pool) = pool {
|
||||||
match info.media_set_label {
|
match info.media_set_label {
|
||||||
Some((set, _)) => {
|
Some(set) => {
|
||||||
if set.uuid != [0u8; 16].into() {
|
if set.uuid != [0u8; 16].into() {
|
||||||
bail!("verify media set label failed - got wrong set uuid");
|
bail!("verify media set label failed - got wrong set uuid");
|
||||||
}
|
}
|
||||||
|
@ -437,31 +437,31 @@ fn write_media_label(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
returns: {
|
returns: {
|
||||||
type: MediaLabelInfoFlat,
|
type: MediaIdFlat,
|
||||||
},
|
},
|
||||||
)]
|
)]
|
||||||
/// Read media label
|
/// Read media label
|
||||||
pub async fn read_label(drive: String) -> Result<MediaLabelInfoFlat, Error> {
|
pub async fn read_label(drive: String) -> Result<MediaIdFlat, Error> {
|
||||||
|
|
||||||
let (config, _digest) = config::drive::config()?;
|
let (config, _digest) = config::drive::config()?;
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let mut drive = open_drive(&config, &drive)?;
|
let mut drive = open_drive(&config, &drive)?;
|
||||||
|
|
||||||
let info = drive.read_label()?;
|
let media_id = drive.read_label()?;
|
||||||
|
|
||||||
let info = match info {
|
let media_id = match media_id {
|
||||||
Some(info) => {
|
Some(media_id) => {
|
||||||
let mut flat = MediaLabelInfoFlat {
|
let mut flat = MediaIdFlat {
|
||||||
uuid: info.label.uuid.to_string(),
|
uuid: media_id.label.uuid.to_string(),
|
||||||
changer_id: info.label.changer_id.clone(),
|
changer_id: media_id.label.changer_id.clone(),
|
||||||
ctime: info.label.ctime,
|
ctime: media_id.label.ctime,
|
||||||
media_set_ctime: None,
|
media_set_ctime: None,
|
||||||
media_set_uuid: None,
|
media_set_uuid: None,
|
||||||
pool: None,
|
pool: None,
|
||||||
seq_nr: None,
|
seq_nr: None,
|
||||||
};
|
};
|
||||||
if let Some((set, _)) = info.media_set_label {
|
if let Some(set) = media_id.media_set_label {
|
||||||
flat.pool = Some(set.pool.clone());
|
flat.pool = Some(set.pool.clone());
|
||||||
flat.seq_nr = Some(set.seq_nr);
|
flat.seq_nr = Some(set.seq_nr);
|
||||||
flat.media_set_uuid = Some(set.uuid.to_string());
|
flat.media_set_uuid = Some(set.uuid.to_string());
|
||||||
|
@ -474,7 +474,7 @@ pub async fn read_label(drive: String) -> Result<MediaLabelInfoFlat, Error> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(info)
|
Ok(media_id)
|
||||||
}).await?
|
}).await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,13 +633,13 @@ pub fn update_inventory(
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
worker.log(format!("media '{}' is empty", changer_id));
|
worker.log(format!("media '{}' is empty", changer_id));
|
||||||
}
|
}
|
||||||
Ok(Some(info)) => {
|
Ok(Some(media_id)) => {
|
||||||
if changer_id != info.label.changer_id {
|
if changer_id != media_id.label.changer_id {
|
||||||
worker.warn(format!("label changer ID missmatch ({} != {})", changer_id, info.label.changer_id));
|
worker.warn(format!("label changer ID missmatch ({} != {})", changer_id, media_id.label.changer_id));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
worker.log(format!("inventorize media '{}' with uuid '{}'", changer_id, info.label.uuid));
|
worker.log(format!("inventorize media '{}' with uuid '{}'", changer_id, media_id.label.uuid));
|
||||||
inventory.store(info.into())?;
|
inventory.store(media_id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub struct MediaListEntry {
|
||||||
#[derive(Serialize,Deserialize)]
|
#[derive(Serialize,Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
/// Media label info
|
/// Media label info
|
||||||
pub struct MediaLabelInfoFlat {
|
pub struct MediaIdFlat {
|
||||||
/// Unique ID
|
/// Unique ID
|
||||||
pub uuid: String,
|
pub uuid: String,
|
||||||
/// Media Changer ID or Barcode
|
/// Media Changer ID or Barcode
|
||||||
|
|
|
@ -7,7 +7,6 @@ use anyhow::{bail, format_err, Error};
|
||||||
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
||||||
|
|
||||||
use proxmox::sys::error::SysResult;
|
use proxmox::sys::error::SysResult;
|
||||||
use proxmox::tools::Uuid;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
tape::{
|
tape::{
|
||||||
|
@ -353,7 +352,7 @@ impl TapeDriver for LinuxTapeHandle {
|
||||||
Ok(Box::new(handle))
|
Ok(Box::new(handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_media_set_label(&mut self, media_set_label: &MediaSetLabel) -> Result<Uuid, Error> {
|
fn write_media_set_label(&mut self, media_set_label: &MediaSetLabel) -> Result<(), Error> {
|
||||||
|
|
||||||
let file_number = self.current_file_number()?;
|
let file_number = self.current_file_number()?;
|
||||||
if file_number != 1 {
|
if file_number != 1 {
|
||||||
|
@ -371,7 +370,7 @@ impl TapeDriver for LinuxTapeHandle {
|
||||||
|
|
||||||
self.sync()?; // sync data to tape
|
self.sync()?; // sync data to tape
|
||||||
|
|
||||||
Ok(Uuid::from(header.uuid))
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rewind and put the drive off line (Eject media).
|
/// Rewind and put the drive off line (Eject media).
|
||||||
|
|
|
@ -6,9 +6,8 @@ mod linux_list_drives;
|
||||||
pub use linux_list_drives::*;
|
pub use linux_list_drives::*;
|
||||||
|
|
||||||
use anyhow::{bail, format_err, Error};
|
use anyhow::{bail, format_err, Error};
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize};
|
||||||
|
|
||||||
use proxmox::tools::Uuid;
|
|
||||||
use proxmox::tools::io::ReadExt;
|
use proxmox::tools::io::ReadExt;
|
||||||
use proxmox::api::section_config::SectionConfigData;
|
use proxmox::api::section_config::SectionConfigData;
|
||||||
|
|
||||||
|
@ -20,6 +19,7 @@ use crate::{
|
||||||
tape::{
|
tape::{
|
||||||
TapeWrite,
|
TapeWrite,
|
||||||
TapeRead,
|
TapeRead,
|
||||||
|
MediaId,
|
||||||
file_formats::{
|
file_formats::{
|
||||||
PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0,
|
PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0,
|
||||||
PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0,
|
PROXMOX_BACKUP_MEDIA_SET_LABEL_MAGIC_1_0,
|
||||||
|
@ -34,15 +34,6 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize,Deserialize)]
|
|
||||||
/// Contains `MediaLabel` and `MediaSetLabel`, including additional content Uuids
|
|
||||||
pub struct MediaLabelInfo {
|
|
||||||
pub label: MediaLabel,
|
|
||||||
pub label_uuid: Uuid,
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub media_set_label: Option<(MediaSetLabel, Uuid)>
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tape driver interface
|
/// Tape driver interface
|
||||||
pub trait TapeDriver {
|
pub trait TapeDriver {
|
||||||
|
|
||||||
|
@ -70,9 +61,7 @@ pub trait TapeDriver {
|
||||||
fn write_file<'a>(&'a mut self) -> Result<Box<dyn TapeWrite + 'a>, std::io::Error>;
|
fn write_file<'a>(&'a mut self) -> Result<Box<dyn TapeWrite + 'a>, std::io::Error>;
|
||||||
|
|
||||||
/// Write label to tape (erase tape content)
|
/// Write label to tape (erase tape content)
|
||||||
///
|
fn label_tape(&mut self, label: &MediaLabel) -> Result<(), Error> {
|
||||||
/// This returns the MediaContentHeader uuid (not the media uuid).
|
|
||||||
fn label_tape(&mut self, label: &MediaLabel) -> Result<Uuid, Error> {
|
|
||||||
|
|
||||||
self.rewind()?;
|
self.rewind()?;
|
||||||
|
|
||||||
|
@ -81,7 +70,6 @@ pub trait TapeDriver {
|
||||||
let raw = serde_json::to_string_pretty(&serde_json::to_value(&label)?)?;
|
let raw = serde_json::to_string_pretty(&serde_json::to_value(&label)?)?;
|
||||||
|
|
||||||
let header = MediaContentHeader::new(PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0, raw.len() as u32);
|
let header = MediaContentHeader::new(PROXMOX_BACKUP_MEDIA_LABEL_MAGIC_1_0, raw.len() as u32);
|
||||||
let content_uuid = header.content_uuid();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut writer = self.write_file()?;
|
let mut writer = self.write_file()?;
|
||||||
|
@ -91,22 +79,20 @@ pub trait TapeDriver {
|
||||||
|
|
||||||
self.sync()?; // sync data to tape
|
self.sync()?; // sync data to tape
|
||||||
|
|
||||||
Ok(content_uuid)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the media set label to tape
|
/// Write the media set label to tape
|
||||||
///
|
fn write_media_set_label(&mut self, media_set_label: &MediaSetLabel) -> Result<(), Error>;
|
||||||
/// This returns the MediaContentHeader uuid (not the media uuid).
|
|
||||||
fn write_media_set_label(&mut self, media_set_label: &MediaSetLabel) -> Result<Uuid, Error>;
|
|
||||||
|
|
||||||
/// Read the media label
|
/// Read the media label
|
||||||
///
|
///
|
||||||
/// This tries to read both media labels (label and media_set_label).
|
/// This tries to read both media labels (label and media_set_label).
|
||||||
fn read_label(&mut self) -> Result<Option<MediaLabelInfo>, Error> {
|
fn read_label(&mut self) -> Result<Option<MediaId>, Error> {
|
||||||
|
|
||||||
self.rewind()?;
|
self.rewind()?;
|
||||||
|
|
||||||
let (label, label_uuid) = {
|
let label = {
|
||||||
let mut reader = match self.read_next_file()? {
|
let mut reader = match self.read_next_file()? {
|
||||||
None => return Ok(None), // tape is empty
|
None => return Ok(None), // tape is empty
|
||||||
Some(reader) => reader,
|
Some(reader) => reader,
|
||||||
|
@ -124,14 +110,14 @@ pub trait TapeDriver {
|
||||||
bail!("got unexpected data after label");
|
bail!("got unexpected data after label");
|
||||||
}
|
}
|
||||||
|
|
||||||
(label, Uuid::from(header.uuid))
|
label
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut info = MediaLabelInfo { label, label_uuid, media_set_label: None };
|
let mut media_id = MediaId { label, media_set_label: None };
|
||||||
|
|
||||||
// try to read MediaSet label
|
// try to read MediaSet label
|
||||||
let mut reader = match self.read_next_file()? {
|
let mut reader = match self.read_next_file()? {
|
||||||
None => return Ok(Some(info)),
|
None => return Ok(Some(media_id)),
|
||||||
Some(reader) => reader,
|
Some(reader) => reader,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -147,9 +133,9 @@ pub trait TapeDriver {
|
||||||
bail!("got unexpected data after media set label");
|
bail!("got unexpected data after media set label");
|
||||||
}
|
}
|
||||||
|
|
||||||
info.media_set_label = Some((media_set_label, Uuid::from(header.uuid)));
|
media_id.media_set_label = Some(media_set_label);
|
||||||
|
|
||||||
Ok(Some(info))
|
Ok(Some(media_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Eject media
|
/// Eject media
|
||||||
|
@ -239,7 +225,7 @@ pub fn request_and_load_media(
|
||||||
label: &MediaLabel,
|
label: &MediaLabel,
|
||||||
) -> Result<(
|
) -> Result<(
|
||||||
Box<dyn TapeDriver>,
|
Box<dyn TapeDriver>,
|
||||||
MediaLabelInfo,
|
MediaId,
|
||||||
), Error> {
|
), Error> {
|
||||||
|
|
||||||
match config.sections.get(drive) {
|
match config.sections.get(drive) {
|
||||||
|
@ -254,10 +240,10 @@ pub fn request_and_load_media(
|
||||||
|
|
||||||
let mut handle = drive.open()?;
|
let mut handle = drive.open()?;
|
||||||
|
|
||||||
if let Ok(Some(info)) = handle.read_label() {
|
if let Ok(Some(media_id)) = handle.read_label() {
|
||||||
println!("found media label {} ({})", info.label.changer_id, info.label.uuid.to_string());
|
println!("found media label {} ({})", media_id.label.changer_id, media_id.label.uuid.to_string());
|
||||||
if info.label.uuid == label.uuid {
|
if media_id.label.uuid == label.uuid {
|
||||||
return Ok((Box::new(handle), info));
|
return Ok((Box::new(handle), media_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bail!("read label failed (label all tapes first)");
|
bail!("read label failed (label all tapes first)");
|
||||||
|
@ -279,10 +265,10 @@ pub fn request_and_load_media(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(Some(info)) = handle.read_label() {
|
if let Ok(Some(media_id)) = handle.read_label() {
|
||||||
println!("found media label {} ({})", info.label.changer_id, info.label.uuid.to_string());
|
println!("found media label {} ({})", media_id.label.changer_id, media_id.label.uuid.to_string());
|
||||||
if info.label.uuid == label.uuid {
|
if media_id.label.uuid == label.uuid {
|
||||||
return Ok((Box::new(handle), info));
|
return Ok((Box::new(handle), media_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ use anyhow::{bail, format_err, Error};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use proxmox::tools::{
|
use proxmox::tools::{
|
||||||
Uuid,
|
|
||||||
fs::{replace_file, CreateOptions},
|
fs::{replace_file, CreateOptions},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -308,7 +307,7 @@ impl TapeDriver for VirtualTapeHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_media_set_label(&mut self, media_set_label: &MediaSetLabel) -> Result<Uuid, Error> {
|
fn write_media_set_label(&mut self, media_set_label: &MediaSetLabel) -> Result<(), Error> {
|
||||||
|
|
||||||
let mut status = self.load_status()?;
|
let mut status = self.load_status()?;
|
||||||
match status.current_tape {
|
match status.current_tape {
|
||||||
|
@ -333,7 +332,7 @@ impl TapeDriver for VirtualTapeHandle {
|
||||||
writer.finish(false)?;
|
writer.finish(false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Uuid::from(header.uuid))
|
Ok(())
|
||||||
}
|
}
|
||||||
None => bail!("drive is empty (no tape loaded)."),
|
None => bail!("drive is empty (no tape loaded)."),
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ use crate::{
|
||||||
},
|
},
|
||||||
tape::{
|
tape::{
|
||||||
TAPE_STATUS_DIR,
|
TAPE_STATUS_DIR,
|
||||||
MediaLabelInfo,
|
|
||||||
file_formats::{
|
file_formats::{
|
||||||
MediaLabel,
|
MediaLabel,
|
||||||
MediaSetLabel,
|
MediaSetLabel,
|
||||||
|
@ -47,16 +46,6 @@ pub struct MediaId {
|
||||||
pub media_set_label: Option<MediaSetLabel>,
|
pub media_set_label: Option<MediaSetLabel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MediaLabelInfo> for MediaId {
|
|
||||||
fn from(info: MediaLabelInfo) -> Self {
|
|
||||||
Self {
|
|
||||||
label: info.label.clone(),
|
|
||||||
media_set_label: info.media_set_label.map(|(l, _)| l),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Media Set
|
/// Media Set
|
||||||
///
|
///
|
||||||
/// A List of backup media
|
/// A List of backup media
|
||||||
|
|
|
@ -23,7 +23,9 @@ use proxmox::tools::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backup::BackupDir,
|
backup::BackupDir,
|
||||||
tape::drive::MediaLabelInfo,
|
tape::{
|
||||||
|
MediaId,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// openssl::sha::sha256(b"Proxmox Backup Media Catalog v1.0")[0..8]
|
// openssl::sha::sha256(b"Proxmox Backup Media Catalog v1.0")[0..8]
|
||||||
|
@ -148,11 +150,11 @@ impl MediaCatalog {
|
||||||
/// Creates a temporary, empty catalog database
|
/// Creates a temporary, empty catalog database
|
||||||
pub fn create_temporary_database(
|
pub fn create_temporary_database(
|
||||||
base_path: &Path,
|
base_path: &Path,
|
||||||
label_info: &MediaLabelInfo,
|
media_id: &MediaId,
|
||||||
log_to_stdout: bool,
|
log_to_stdout: bool,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
|
||||||
let uuid = &label_info.label.uuid;
|
let uuid = &media_id.label.uuid;
|
||||||
|
|
||||||
let mut tmp_path = base_path.to_owned();
|
let mut tmp_path = base_path.to_owned();
|
||||||
tmp_path.push(uuid.to_string());
|
tmp_path.push(uuid.to_string());
|
||||||
|
@ -186,10 +188,10 @@ impl MediaCatalog {
|
||||||
|
|
||||||
me.log_to_stdout = log_to_stdout;
|
me.log_to_stdout = log_to_stdout;
|
||||||
|
|
||||||
me.register_label(&label_info.label_uuid, 0)?;
|
me.register_label(&media_id.label.uuid, 0)?;
|
||||||
|
|
||||||
if let Some((_, ref content_uuid)) = label_info.media_set_label {
|
if let Some(ref set) = media_id.media_set_label {
|
||||||
me.register_label(&content_uuid, 1)?;
|
me.register_label(&set.uuid, 1)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
me.pending.extend(&PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_0);
|
me.pending.extend(&PROXMOX_BACKUP_MEDIA_CATALOG_MAGIC_1_0);
|
||||||
|
@ -273,13 +275,13 @@ impl MediaCatalog {
|
||||||
/// Destroy existing catalog, opens a new one
|
/// Destroy existing catalog, opens a new one
|
||||||
pub fn overwrite(
|
pub fn overwrite(
|
||||||
base_path: &Path,
|
base_path: &Path,
|
||||||
label_info: &MediaLabelInfo,
|
media_id: &MediaId,
|
||||||
log_to_stdout: bool,
|
log_to_stdout: bool,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
|
||||||
let uuid = &label_info.label.uuid;
|
let uuid = &media_id.label.uuid;
|
||||||
|
|
||||||
let me = Self::create_temporary_database(base_path, &label_info, log_to_stdout)?;
|
let me = Self::create_temporary_database(base_path, &media_id, log_to_stdout)?;
|
||||||
|
|
||||||
Self::finish_temporary_database(base_path, uuid, true)?;
|
Self::finish_temporary_database(base_path, uuid, true)?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue