From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 070801FF185 for ; Fri, 08 May 2026 11:34:42 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1256F12EF5; Fri, 8 May 2026 11:34:41 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup] fix #7562: api/ui: make tape formatting in changer more consistent Date: Fri, 8 May 2026 11:32:06 +0200 Message-ID: <20260508093426.1762797-1-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.050 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [record.data,drive.rs] Message-ID-Hash: YC53EC2LACW5L5W6BX3COFZPLEO3WRJX X-Message-ID-Hash: YC53EC2LACW5L5W6BX3COFZPLEO3WRJX X-MailFrom: d.csapak@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: the 'format-media' api call takes a 'label-text' which is used for two things simultaneously: 1. load a tape from a slot into the drive (where it's barcode is the given label-text) 2. check if the label on the tape is the one given The web ui uses the fact nr. 1 as a feature to load + format in one step, to reduce the necessary user actions, but this has a drawback: if the user wants to load+format a tape this way that is either empty or has unrelated data on it, we refuse to format it due to fact nr. 2. To improve this, introduce a separate parameter for loading a tape with a given barcode, and using the label-text separately for checking the on tape label. This can be used in the ui to handle all use cases: * load + format a labeled tape * load + format an empty tape * load + format a tape with unrelated data * check label + format without loading from a slot * force format without any checking Signed-off-by: Dominik Csapak --- I guess this could be seen as a breaking change, as we now require a new parameter for loading the tape into the drive, but I currently don't see a good way to keep this behavior while also fixing the bug properly. (Without having a flag that uses the new behavior, that would still be broken for the old one...) src/api2/tape/drive.rs | 11 ++++++++--- www/tape/ChangerStatus.js | 12 ++++++++++-- www/tape/TapeInventory.js | 5 +++-- www/tape/window/Erase.js | 14 ++++++++++++-- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/api2/tape/drive.rs b/src/api2/tape/drive.rs index 1a45ae406..c981fbb94 100644 --- a/src/api2/tape/drive.rs +++ b/src/api2/tape/drive.rs @@ -269,6 +269,10 @@ pub fn unload( optional: true, default: true, }, + "load-barcode": { + schema: MEDIA_LABEL_SCHEMA, + optional: true, + }, "label-text": { schema: MEDIA_LABEL_SCHEMA, optional: true, @@ -286,6 +290,7 @@ pub fn unload( pub fn format_media( drive: String, fast: Option, + load_barcode: Option, label_text: Option, rpcenv: &mut dyn RpcEnvironment, ) -> Result { @@ -295,10 +300,10 @@ pub fn format_media( "format-media", Some(drive.clone()), move |_worker, config| { - if let Some(ref label) = label_text { - info!("try to load media '{label}'"); + if let Some(barcode) = load_barcode { + info!("try to load media '{barcode}'"); if let Some((mut changer, _)) = media_changer(&config, &drive)? { - changer.load_media(label)?; + changer.load_media(&barcode)?; } } diff --git a/www/tape/ChangerStatus.js b/www/tape/ChangerStatus.js index e5d6d5d76..c979024a1 100644 --- a/www/tape/ChangerStatus.js +++ b/www/tape/ChangerStatus.js @@ -164,10 +164,17 @@ Ext.define('PBS.TapeManagement.ChangerStatus', { 'format-inserted': function (button, event, record) { let me = this; + let params = {}; + if (record.data['is-labeled']) { + params = { + 'label-text': record.data['label-text'], + }; + } let view = me.getView(); PBS.Utils.driveCommand(record.data.name, 'format-media', { waitMsgTarget: view, method: 'POST', + params, success: function (response) { Ext.create('Proxmox.window.TaskProgress', { upid: response.result.data, @@ -182,12 +189,13 @@ Ext.define('PBS.TapeManagement.ChangerStatus', { format: function (v, rI, cI, button, el, record) { let me = this; let view = me.getView(); - let label = record.data['label-text']; + let barcode = record.data['label-text']; let changer = encodeURIComponent(view.changer); let singleDrive = me.drives.length === 1 ? me.drives[0] : undefined; Ext.create('PBS.TapeManagement.EraseWindow', { - label, + barcode, + isLabeled: record.data['is-labeled'], changer, singleDrive, listeners: { diff --git a/www/tape/TapeInventory.js b/www/tape/TapeInventory.js index 85e9fdea8..1e12a78e7 100644 --- a/www/tape/TapeInventory.js +++ b/www/tape/TapeInventory.js @@ -44,14 +44,15 @@ Ext.define('PBS.TapeManagement.TapeInventory', { if (!selection || selection.length < 1) { return; } - let label = selection[0].data['label-text']; + let barcode = selection[0].data['label-text']; let inChanger = selection[0].data.location.startsWith('online-'); let changer; if (inChanger) { changer = selection[0].data.location.slice('online-'.length); } Ext.create('PBS.TapeManagement.EraseWindow', { - label, + barcode, + isLabeled: true, changer, listeners: { destroy: function () { diff --git a/www/tape/window/Erase.js b/www/tape/window/Erase.js index 41df1a38f..e815f8e65 100644 --- a/www/tape/window/Erase.js +++ b/www/tape/window/Erase.js @@ -3,16 +3,18 @@ Ext.define('PBS.TapeManagement.EraseWindow', { mixins: ['Proxmox.Mixin.CBind'], changer: undefined, - label: undefined, + barcode: undefined, + isLabeled: false, cbindData: function (config) { let me = this; return { + label: me.isLabeled ? me.barcode : undefined, singleDrive: me.singleDrive, hasSingleDrive: !!me.singleDrive, warning: Ext.String.format( gettext("Are you sure you want to format tape '{0}' ?"), - me.label, + me.barcode, ), }; }, @@ -66,10 +68,18 @@ Ext.define('PBS.TapeManagement.EraseWindow', { hidden: '{changer}', }, }, + { + xtype: 'hidden', + name: 'load-barcode', + cbind: { + value: '{barcode}', + }, + }, { xtype: 'hidden', name: 'label-text', cbind: { + submitValue: '{isLabeled}', value: '{label}', }, }, -- 2.47.3