fix #5412: ui: backup now: add fleecing option

Fleecing can be enabled for backup jobs, but not for a manual backup
via 'Backup now', where only a default in the node's vzdump.conf
applies. So a VM that needs fleecing to not stall during the backup can
not be backed up safely from the UI without changing that default.

Add the 'Fleecing' and 'Fleecing Storage' fields of the backup job
editor, for VMs only, as fleecing is not used for containers. Like
there, the storage is required if fleecing is enabled, so the 'Backup'
button stays disabled until one is selected. The fields start with the
node's defaults.

Only send the fleecing option if it was changed. The API checks for
'Datastore.AllocateSpace' on the fleecing storage of the option, but
not on the one of the node's default, so always sending it would make
manual backups fail for users without that permission on nodes with
fleecing enabled by default.

Signed-off-by: Michal Fox <me@dualfroz.com>
This commit is contained in:
dualfroz committed 2026-10-03 03:19:01 +02:00
1 parent 94c1c98e32
commit 678da1b8ed
1 file changed
+56 -1
+56 -1
View File
@@ -189,6 +189,14 @@ Ext.define('PVE.window.Backup', {
if (!initialDefaults && data.mode !== undefined) {
modeSelector.setValue(data.mode);
}
if (!initialDefaults && me.vmtype === 'qemu' && data.fleecing) {
fleecingStorageSelector.setValue(data.fleecing.storage);
fleecingCheckbox.setValue(data.fleecing.enabled);
// only changed fleecing settings are sent, so that the node's
// defaults keep working without permissions on their storage
fleecingStorageSelector.resetOriginalValue();
fleecingCheckbox.resetOriginalValue();
}
if (!initialDefaults && (data['notes-template'] ?? false)) {
me.down('field[name=notes-template]').setValue(
PVE.Utils.unEscapeNotesTemplate(data['notes-template']),
@@ -245,10 +253,45 @@ Ext.define('PVE.window.Backup', {
padding: '0 0 1 0',
});
let fleecingStorageSelector = Ext.create('PVE.form.StorageSelector', {
nodename: me.nodename,
name: 'fleecing-storage',
fieldLabel: gettext('Fleecing Storage'),
storageContent: 'images',
allowBlank: false,
disabled: true,
hidden: me.vmtype !== 'qemu',
});
let fleecingCheckbox = Ext.create('Proxmox.form.Checkbox', {
name: 'fleecing-enabled',
checked: false,
hidden: me.vmtype !== 'qemu',
uncheckedValue: 0,
fieldLabel: gettext('Fleecing'),
autoEl: {
tag: 'div',
'data-qtip': gettext(
'Backup write cache that can reduce IO pressure inside guests (VMs only).',
),
},
handler: function (checkbox, value) {
fleecingStorageSelector.setDisabled(!value);
fleecingStorageSelector.validate();
},
});
me.formPanel = Ext.create('Proxmox.panel.InputPanel', {
bodyPadding: 10,
border: false,
column1: [storagesel, modeSelector, protectedCheckbox, pbsChangeDetection],
column1: [
storagesel,
modeSelector,
protectedCheckbox,
fleecingCheckbox,
fleecingStorageSelector,
pbsChangeDetection,
],
column2: [compressionSelector, notificationModeSelector, mailtoField, removeCheckbox],
columnB: [
{
@@ -331,6 +374,14 @@ Ext.define('PVE.window.Backup', {
params.protected = values.protected;
}
if (fleecingCheckbox.isDirty() || fleecingStorageSelector.isDirty()) {
let fleecing = { enabled: values['fleecing-enabled'] };
if (values['fleecing-enabled']) {
fleecing.storage = values['fleecing-storage'];
}
params.fleecing = PVE.Parser.printPropertyString(fleecing);
}
if (values['pbs-change-detection-mode']) {
params['pbs-change-detection-mode'] = values['pbs-change-detection-mode'];
}
@@ -369,6 +420,10 @@ Ext.define('PVE.window.Backup', {
},
});
fleecingStorageSelector.on('validitychange', (field, valid) =>
submitBtn.setDisabled(!valid),
);
var helpBtn = Ext.create('Proxmox.button.Help', {
onlineHelp: 'chapter_vzdump',
listenToGlobalEvent: false,