diff --git a/src/api2/tape/media.rs b/src/api2/tape/media.rs index 2888aad1..7876d206 100644 --- a/src/api2/tape/media.rs +++ b/src/api2/tape/media.rs @@ -20,6 +20,7 @@ use crate::{ MEDIA_LABEL_SCHEMA, MEDIA_UUID_SCHEMA, MEDIA_SET_UUID_SCHEMA, + CHANGER_NAME_SCHEMA, MediaPoolConfig, MediaListEntry, MediaStatus, @@ -50,6 +51,11 @@ use crate::{ optional: true, default: true, }, + "update-status-changer": { + // only update status for a single changer + schema: CHANGER_NAME_SCHEMA, + optional: true, + }, }, }, returns: { @@ -64,6 +70,7 @@ use crate::{ pub async fn list_media( pool: Option, update_status: bool, + update_status_changer: Option, ) -> Result, Error> { let (config, _digest) = config::media_pool::config()?; @@ -73,7 +80,7 @@ pub async fn list_media( let catalogs = tokio::task::spawn_blocking(move || { if update_status { // update online media status - if let Err(err) = update_online_status(status_path) { + if let Err(err) = update_online_status(status_path, update_status_changer.as_deref()) { eprintln!("{}", err); eprintln!("update online media status failed - using old state"); } diff --git a/src/bin/proxmox_tape/media.rs b/src/bin/proxmox_tape/media.rs index 4bd0474b..bcbb9170 100644 --- a/src/bin/proxmox_tape/media.rs +++ b/src/bin/proxmox_tape/media.rs @@ -15,11 +15,13 @@ use proxmox_backup::{ self, types::{ MEDIA_POOL_NAME_SCHEMA, + CHANGER_NAME_SCHEMA, MediaStatus, MediaListEntry, }, tape::media::MediaContentListFilter, }, + config::drive::complete_changer_name, tape::{ complete_media_label_text, complete_media_uuid, @@ -37,6 +39,7 @@ pub fn media_commands() -> CommandLineInterface { "list", CliCommand::new(&API_METHOD_LIST_MEDIA) .completion_cb("pool", complete_pool_name) + .completion_cb("update-status-changer", complete_changer_name) ) .insert( "destroy", @@ -64,6 +67,17 @@ pub fn media_commands() -> CommandLineInterface { schema: MEDIA_POOL_NAME_SCHEMA, optional: true, }, + "update-status": { + description: "Try to update tape library status (check what tapes are online).", + type: bool, + optional: true, + default: true, + }, + "update-status-changer": { + // only update status for a single changer + schema: CHANGER_NAME_SCHEMA, + optional: true, + }, "output-format": { schema: OUTPUT_FORMAT, optional: true, diff --git a/src/tape/changer/online_status_map.rs b/src/tape/changer/online_status_map.rs index c65cceaf..e80ba2f7 100644 --- a/src/tape/changer/online_status_map.rs +++ b/src/tape/changer/online_status_map.rs @@ -122,8 +122,8 @@ pub fn mtx_status_to_online_set(status: &MtxStatus, inventory: &Inventory) -> Ha /// Update online media status /// -/// Simply ask all changer devices. -pub fn update_online_status(state_path: &Path) -> Result { +/// For a single 'changer', or else simply ask all changer devices. +pub fn update_online_status(state_path: &Path, changer: Option<&str>) -> Result { let (config, _digest) = crate::config::drive::config()?; @@ -133,21 +133,36 @@ pub fn update_online_status(state_path: &Path) -> Result let mut map = OnlineStatusMap::new(&config)?; - for mut changer in changers { - let status = match changer.status() { + let mut found_changer = false; + + for mut changer_config in changers { + if let Some(changer) = changer { + if changer != &changer_config.name { + continue; + } + found_changer = true; + } + let status = match changer_config.status() { Ok(status) => status, Err(err) => { - eprintln!("unable to get changer '{}' status - {}", changer.name, err); + eprintln!("unable to get changer '{}' status - {}", changer_config.name, err); continue; } }; let online_set = mtx_status_to_online_set(&status, &inventory); - map.update_online_status(&changer.name, online_set)?; + map.update_online_status(&changer_config.name, online_set)?; } let vtapes: Vec = config.convert_to_typed_array("virtual")?; for mut vtape in vtapes { + if let Some(changer) = changer { + if changer != &vtape.name { + continue; + } + found_changer = true; + } + let media_list = match vtape.online_media_label_texts() { Ok(media_list) => media_list, Err(err) => { @@ -165,6 +180,12 @@ pub fn update_online_status(state_path: &Path) -> Result map.update_online_status(&vtape.name, online_set)?; } + if let Some(changer) = changer { + if !found_changer { + bail!("update_online_status failed - no such changer '{}'", changer); + } + } + inventory.update_online_status(&map)?; Ok(map)