mirror of
https://git.proxmox.com/git/proxmox-backup
synced 2025-04-30 00:01:35 +00: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:
parent
4ebb08a5f0
commit
b5af9333f8
@ -93,6 +93,9 @@ pub struct DriveListEntry {
|
|||||||
/// the state of the drive if locked
|
/// the state of the drive if locked
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub state: Option<String>,
|
pub state: Option<String>,
|
||||||
|
/// Current device activity
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub activity: Option<DeviceActivity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[api()]
|
#[api()]
|
||||||
|
@ -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
|
/// Access to file descriptor - useful for testing
|
||||||
pub fn file_mut(&mut self) -> &mut File {
|
pub fn file_mut(&mut self) -> &mut File {
|
||||||
&mut self.file
|
&mut self.file
|
||||||
|
@ -3,6 +3,7 @@ use std::panic::UnwindSafe;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{bail, format_err, Error};
|
use anyhow::{bail, format_err, Error};
|
||||||
|
use pbs_tape::sg_tape::SgTape;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use proxmox_router::{
|
use proxmox_router::{
|
||||||
@ -1411,6 +1412,12 @@ pub fn catalog_media(
|
|||||||
schema: CHANGER_NAME_SCHEMA,
|
schema: CHANGER_NAME_SCHEMA,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
"query-activity": {
|
||||||
|
type: bool,
|
||||||
|
description: "If true, queries and returns the drive activity for each drive.",
|
||||||
|
optional: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
returns: {
|
returns: {
|
||||||
@ -1428,6 +1435,7 @@ pub fn catalog_media(
|
|||||||
/// List drives
|
/// List drives
|
||||||
pub fn list_drives(
|
pub fn list_drives(
|
||||||
changer: Option<String>,
|
changer: Option<String>,
|
||||||
|
query_activity: bool,
|
||||||
_param: Value,
|
_param: Value,
|
||||||
rpcenv: &mut dyn RpcEnvironment,
|
rpcenv: &mut dyn RpcEnvironment,
|
||||||
) -> Result<Vec<DriveListEntry>, Error> {
|
) -> Result<Vec<DriveListEntry>, Error> {
|
||||||
@ -1454,10 +1462,16 @@ pub fn list_drives(
|
|||||||
|
|
||||||
let info = lookup_device_identification(<o_drives, &drive.path);
|
let info = lookup_device_identification(<o_drives, &drive.path);
|
||||||
let state = get_tape_device_state(&config, &drive.name)?;
|
let state = get_tape_device_state(&config, &drive.name)?;
|
||||||
|
let activity = if query_activity {
|
||||||
|
SgTape::device_activity(&drive).ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let entry = DriveListEntry {
|
let entry = DriveListEntry {
|
||||||
config: drive,
|
config: drive,
|
||||||
info,
|
info,
|
||||||
state,
|
state,
|
||||||
|
activity,
|
||||||
};
|
};
|
||||||
list.push(entry);
|
list.push(entry);
|
||||||
}
|
}
|
||||||
|
@ -721,8 +721,11 @@ Ext.define('PBS.Utils', {
|
|||||||
return PBS.Utils.tapeDriveActivities[value] ?? value;
|
return PBS.Utils.tapeDriveActivities[value] ?? value;
|
||||||
},
|
},
|
||||||
|
|
||||||
renderDriveState: function(value, md) {
|
renderDriveState: function(value, md, rec) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
if (rec?.data?.activity && rec?.data?.activity !== 'no-activity') {
|
||||||
|
return PBS.Utils.renderDriveActivity(rec.data.activity);
|
||||||
|
}
|
||||||
return gettext('Idle');
|
return gettext('Idle');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Ext.define('pbs-slot-model', {
|
Ext.define('pbs-slot-model', {
|
||||||
extend: 'Ext.data.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',
|
name: 'is-blocked',
|
||||||
calculate: function(data) {
|
calculate: function(data) {
|
||||||
@ -488,7 +488,7 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
|
|||||||
});
|
});
|
||||||
let drives_fut = Proxmox.Async.api2({
|
let drives_fut = Proxmox.Async.api2({
|
||||||
timeout: 5*60*1000,
|
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({
|
let tapes_fut = Proxmox.Async.api2({
|
||||||
@ -852,6 +852,13 @@ Ext.define('PBS.TapeManagement.ChangerStatus', {
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
renderer: Ext.htmlEncode,
|
renderer: Ext.htmlEncode,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: gettext('Activity'),
|
||||||
|
dataIndex: 'activity',
|
||||||
|
renderer: PBS.Utils.renderDriveActivity,
|
||||||
|
hidden: true,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: gettext('State'),
|
text: gettext('State'),
|
||||||
dataIndex: 'state',
|
dataIndex: 'state',
|
||||||
|
Loading…
Reference in New Issue
Block a user