tape: show catalog status in media list

This commit is contained in:
Dietmar Maurer 2021-01-09 10:24:48 +01:00
parent c7926d8e8c
commit 0bf1c314da
4 changed files with 43 additions and 3 deletions

View File

@ -58,12 +58,15 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
let status_path = Path::new(TAPE_STATUS_DIR); let status_path = Path::new(TAPE_STATUS_DIR);
tokio::task::spawn_blocking(move || { let catalogs = tokio::task::spawn_blocking(move || {
// update online media status
if let Err(err) = update_online_status(status_path) { if let Err(err) = update_online_status(status_path) {
eprintln!("{}", err); eprintln!("{}", err);
eprintln!("update online media status failed - using old state"); eprintln!("update online media status failed - using old state");
} }
}).await?; // test what catalog files we have
MediaCatalog::media_with_catalogs(status_path)
}).await??;
let mut list = Vec::new(); let mut list = Vec::new();
@ -100,12 +103,20 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
.unwrap_or_else(|_| set.uuid.to_string()) .unwrap_or_else(|_| set.uuid.to_string())
}); });
let catalog_ok = if media.media_set_label().is_none() {
// Media is empty, we need no catalog
true
} else {
catalogs.contains(media.uuid())
};
list.push(MediaListEntry { list.push(MediaListEntry {
uuid: media.uuid().to_string(), uuid: media.uuid().to_string(),
changer_id: media.changer_id().to_string(), changer_id: media.changer_id().to_string(),
pool: Some(pool_name.to_string()), pool: Some(pool_name.to_string()),
location: media.location().clone(), location: media.location().clone(),
status: *media.status(), status: *media.status(),
catalog: catalog_ok,
expired, expired,
media_set_uuid, media_set_uuid,
media_set_name, media_set_name,
@ -131,6 +142,7 @@ pub async fn list_media(pool: Option<String>) -> Result<Vec<MediaListEntry>, Err
changer_id: media_id.label.changer_id.to_string(), changer_id: media_id.label.changer_id.to_string(),
location, location,
status, status,
catalog: true, // empty, so we do not need a catalog
expired: false, expired: false,
media_set_uuid: None, media_set_uuid: None,
media_set_name: None, media_set_name: None,

View File

@ -29,6 +29,8 @@ pub struct MediaListEntry {
pub status: MediaStatus, pub status: MediaStatus,
/// Expired flag /// Expired flag
pub expired: bool, pub expired: bool,
/// Catalog status OK
pub catalog: bool,
/// Media set name /// Media set name
#[serde(skip_serializing_if="Option::is_none")] #[serde(skip_serializing_if="Option::is_none")]
pub media_set_name: Option<String>, pub media_set_name: Option<String>,

View File

@ -104,6 +104,14 @@ async fn list_media(
}) })
} }
fn catalog_status(value: &Value, _record: &Value) -> Result<String, Error> {
let catalog_ok = value.as_bool().unwrap();
if catalog_ok {
Ok(String::from("ok"))
} else {
Ok(String::from("missing"))
}
}
let options = default_table_format_options() let options = default_table_format_options()
.sortby("pool", false) .sortby("pool", false)
.sortby("media-set-uuid", false) .sortby("media-set-uuid", false)
@ -115,6 +123,7 @@ async fn list_media(
.column(ColumnConfig::new("seq-nr")) .column(ColumnConfig::new("seq-nr"))
.column(ColumnConfig::new("status").renderer(render_status)) .column(ColumnConfig::new("status").renderer(render_status))
.column(ColumnConfig::new("location")) .column(ColumnConfig::new("location"))
.column(ColumnConfig::new("catalog").renderer(catalog_status))
.column(ColumnConfig::new("uuid")) .column(ColumnConfig::new("uuid"))
.column(ColumnConfig::new("media-set-uuid")) .column(ColumnConfig::new("media-set-uuid"))
; ;

View File

@ -3,7 +3,7 @@ use std::fs::File;
use std::io::{Write, Read, BufReader, Seek, SeekFrom}; use std::io::{Write, Read, BufReader, Seek, SeekFrom};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::path::Path; use std::path::Path;
use std::collections::HashMap; use std::collections::{HashSet, HashMap};
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
use endian_trait::Endian; use endian_trait::Endian;
@ -22,6 +22,7 @@ use proxmox::tools::{
}; };
use crate::{ use crate::{
tools::fs::read_subdir,
backup::BackupDir, backup::BackupDir,
tape::{ tape::{
MediaId, MediaId,
@ -58,6 +59,22 @@ pub struct MediaCatalog {
impl MediaCatalog { impl MediaCatalog {
/// List media with catalogs
pub fn media_with_catalogs(base_path: &Path) -> Result<HashSet<Uuid>, Error> {
let mut catalogs = HashSet::new();
for entry in read_subdir(libc::AT_FDCWD, base_path)? {
let entry = entry?;
let name = unsafe { entry.file_name_utf8_unchecked() };
if !name.ends_with(".log") { continue; }
if let Ok(uuid) = Uuid::parse_str(&name[..(name.len()-4)]) {
catalogs.insert(uuid);
}
}
Ok(catalogs)
}
/// Test if a catalog exists /// Test if a catalog exists
pub fn exists(base_path: &Path, uuid: &Uuid) -> bool { pub fn exists(base_path: &Path, uuid: &Uuid) -> bool {
let mut path = base_path.to_owned(); let mut path = base_path.to_owned();