From b5af9333f87a34bbf96941b4ebbf7a0373ffcb71 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Mon, 13 May 2024 12:49:26 +0200 Subject: [PATCH] tape: include drive activity in status Since we don't query each drives status seperately, but rely on a single call to the drives listing parameter for that, we now add the option to query the activity there too. This makes that data avaiable for us to show in a seperate (by default hidden) column. Also we show the activity in the 'State' column when the drive is idle from our perspective. This is useful when e.g. an LTO-9 tape is loaded the first time and is calibrating, since that happens automatically. Signed-off-by: Dominik Csapak --- pbs-api-types/src/tape/drive.rs | 3 +++ pbs-tape/src/sg_tape.rs | 6 ++++++ src/api2/tape/drive.rs | 14 ++++++++++++++ www/Utils.js | 5 ++++- www/tape/ChangerStatus.js | 11 +++++++++-- 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/pbs-api-types/src/tape/drive.rs b/pbs-api-types/src/tape/drive.rs index caa6b3b3..2b788bd6 100644 --- a/pbs-api-types/src/tape/drive.rs +++ b/pbs-api-types/src/tape/drive.rs @@ -93,6 +93,9 @@ pub struct DriveListEntry { /// the state of the drive if locked #[serde(skip_serializing_if = "Option::is_none")] pub state: Option, + /// Current device activity + #[serde(skip_serializing_if = "Option::is_none")] + pub activity: Option, } #[api()] diff --git a/pbs-tape/src/sg_tape.rs b/pbs-tape/src/sg_tape.rs index 5cda9194..f30481b3 100644 --- a/pbs-tape/src/sg_tape.rs +++ b/pbs-tape/src/sg_tape.rs @@ -172,6 +172,12 @@ impl SgTape { }) } + /// Read device activity + pub fn device_activity(config: &LtoTapeDrive) -> Result { + let mut file = open_lto_tape_device(&config.path)?; + read_device_activity(&mut file) + } + /// Access to file descriptor - useful for testing pub fn file_mut(&mut self) -> &mut File { &mut self.file diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs index 5a5d39d9..7a791e09 100644 --- a/src/api2/tape/drive.rs +++ b/src/api2/tape/drive.rs @@ -3,6 +3,7 @@ use std::panic::UnwindSafe; use std::sync::Arc; use anyhow::{bail, format_err, Error}; +use pbs_tape::sg_tape::SgTape; use serde_json::Value; use proxmox_router::{ @@ -1411,6 +1412,12 @@ pub fn catalog_media( schema: CHANGER_NAME_SCHEMA, optional: true, }, + "query-activity": { + type: bool, + description: "If true, queries and returns the drive activity for each drive.", + optional: true, + default: false, + }, }, }, returns: { @@ -1428,6 +1435,7 @@ pub fn catalog_media( /// List drives pub fn list_drives( changer: Option, + query_activity: bool, _param: Value, rpcenv: &mut dyn RpcEnvironment, ) -> Result, Error> { @@ -1454,10 +1462,16 @@ pub fn list_drives( let info = lookup_device_identification(<o_drives, &drive.path); let state = get_tape_device_state(&config, &drive.name)?; + let activity = if query_activity { + SgTape::device_activity(&drive).ok() + } else { + None + }; let entry = DriveListEntry { config: drive, info, state, + activity, }; list.push(entry); } diff --git a/www/Utils.js b/www/Utils.js index df03a4c8..4853be36 100644 --- a/www/Utils.js +++ b/www/Utils.js @@ -721,8 +721,11 @@ Ext.define('PBS.Utils', { return PBS.Utils.tapeDriveActivities[value] ?? value; }, - renderDriveState: function(value, md) { + renderDriveState: function(value, md, rec) { if (!value) { + if (rec?.data?.activity && rec?.data?.activity !== 'no-activity') { + return PBS.Utils.renderDriveActivity(rec.data.activity); + } return gettext('Idle'); } diff --git a/www/tape/ChangerStatus.js b/www/tape/ChangerStatus.js index fdafc459..e18af90e 100644 --- a/www/tape/ChangerStatus.js +++ b/www/tape/ChangerStatus.js @@ -1,6 +1,6 @@ Ext.define('pbs-slot-model', { extend: 'Ext.data.Model', - fields: ['entry-id', 'label-text', 'is-labeled', ' model', 'name', 'vendor', 'serial', 'state', 'status', 'pool', + fields: ['entry-id', 'label-text', 'is-labeled', ' model', 'name', 'vendor', 'serial', 'state', 'status', 'pool', 'activity', { name: 'is-blocked', calculate: function(data) { @@ -488,7 +488,7 @@ Ext.define('PBS.TapeManagement.ChangerStatus', { }); let drives_fut = Proxmox.Async.api2({ timeout: 5*60*1000, - url: `/api2/extjs/tape/drive?changer=${encodeURIComponent(changer)}`, + url: `/api2/extjs/tape/drive?query-activity=true&changer=${encodeURIComponent(changer)}`, }); let tapes_fut = Proxmox.Async.api2({ @@ -852,6 +852,13 @@ Ext.define('PBS.TapeManagement.ChangerStatus', { flex: 1, renderer: Ext.htmlEncode, }, + { + text: gettext('Activity'), + dataIndex: 'activity', + renderer: PBS.Utils.renderDriveActivity, + hidden: true, + flex: 1, + }, { text: gettext('State'), dataIndex: 'state',