5
0
mirror of git://git.proxmox.com/git/proxmox-backup.git synced 2025-03-07 00:58:32 +03:00

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 <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2024-05-13 12:49:26 +02:00 committed by Dietmar Maurer
parent 4ebb08a5f0
commit b5af9333f8
5 changed files with 36 additions and 3 deletions

View File

@ -93,6 +93,9 @@ pub struct DriveListEntry {
/// the state of the drive if locked
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
/// Current device activity
#[serde(skip_serializing_if = "Option::is_none")]
pub activity: Option<DeviceActivity>,
}
#[api()]

View File

@ -172,6 +172,12 @@ impl SgTape {
})
}
/// Read device activity
pub fn device_activity(config: &LtoTapeDrive) -> Result<DeviceActivity, Error> {
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

View File

@ -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<String>,
query_activity: bool,
_param: Value,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<DriveListEntry>, Error> {
@ -1454,10 +1462,16 @@ pub fn list_drives(
let info = lookup_device_identification(&lto_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);
}

View File

@ -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');
}

View File

@ -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',