Files
proxmox-git-pve-manager/www/manager6/panel/BackupAdvancedOptions.js
T

307 lines
10 KiB
JavaScript

/*
* Input panel for advanced backup options intended to be used as part of an edit/create window.
*/
Ext.define('PVE.panel.BackupAdvancedOptions', {
extend: 'Proxmox.panel.InputPanel',
xtype: 'pveBackupAdvancedOptionsPanel',
mixins: ['Proxmox.Mixin.CBind'],
cbindData: function () {
let me = this;
me.isCreate = !!me.isCreate;
return {};
},
viewModel: {
data: {},
},
controller: {
xclass: 'Ext.app.ViewController',
toggleFleecing: function (cb, value) {
let me = this;
me.lookup('fleecingStorage').setDisabled(!value);
},
control: {
'proxmoxcheckbox[reference=fleecingEnabled]': {
change: 'toggleFleecing',
},
},
},
onGetValues: function (formValues) {
let me = this;
if (me.needMask) {
// isMasked() may not yet be true if not rendered once
return {};
}
if (!formValues.id && me.isCreate) {
formValues.id = 'backup-' + Ext.data.identifier.Uuid.Global.generate().slice(0, 13);
}
let options = {};
if (!me.isCreate) {
options.delete = []; // to avoid having to check this all the time
}
const deletePropertyOnEdit = me.isCreate
? () => {
/* no-op on create */
}
: (key) => options.delete.push(key);
let fleecing = {},
fleecingOptions = ['fleecing-enabled', 'fleecing-storage'];
let performance = {},
performanceOptions = ['max-workers', 'pbs-entries-max'];
for (const [key, value] of Object.entries(formValues)) {
if (performanceOptions.includes(key)) {
performance[key] = value;
// deleteEmpty is not currently implemented for pveBandwidthField
} else if (key === 'bwlimit' && value === '') {
deletePropertyOnEdit('bwlimit');
} else if (key === 'delete') {
if (Array.isArray(value)) {
value
.filter((opt) => !performanceOptions.includes(opt))
.forEach((opt) => deletePropertyOnEdit(opt));
} else if (!performanceOptions.includes(formValues.delete)) {
deletePropertyOnEdit(value);
}
} else if (fleecingOptions.includes(key)) {
let fleecingKey = key.slice('fleecing-'.length);
fleecing[fleecingKey] = value;
} else {
options[key] = value;
}
}
if (Object.keys(performance).length > 0) {
options.performance = PVE.Parser.printPropertyString(performance);
} else {
deletePropertyOnEdit('performance');
}
if (Object.keys(fleecing).length > 0) {
options.fleecing = PVE.Parser.printPropertyString(fleecing);
} else {
deletePropertyOnEdit('fleecing');
}
if (me.isCreate) {
delete options.delete;
}
return options;
},
onSetValues: function (values) {
if (values.fleecing) {
for (const [key, value] of Object.entries(values.fleecing)) {
values[`fleecing-${key}`] = value;
}
delete values.fleecing;
}
if (values['pbs-change-detection-mode'] === '__default__') {
delete values['pbs-change-detection-mode'];
}
return values;
},
updateCompression: function (value, disabled) {
this.lookup('zstdThreadCount').setDisabled(disabled || value !== 'zstd');
},
items: [
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'pmxDisplayEditField',
vtype: 'ConfigId',
fieldLabel: gettext('Job ID'),
emptyText: gettext('Autogenerate'),
name: 'id',
allowBlank: true,
cbind: {
editable: '{isCreate}',
},
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: gettext('Can be used in notification matchers to match this job.'),
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'pveBandwidthField',
name: 'bwlimit',
fieldLabel: gettext('Bandwidth Limit'),
emptyText: gettext('Fallback'),
backendUnit: 'KiB',
allowZero: true,
emptyValue: '',
autoEl: {
tag: 'div',
'data-qtip': Ext.String.format(gettext('Use {0} for unlimited'), 0),
},
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: `${gettext('Limit I/O bandwidth.')} ${Ext.String.format(gettext('Schema default: {0}'), 0)}`,
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'proxmoxintegerfield',
name: 'zstd',
reference: 'zstdThreadCount',
fieldLabel: gettext('Zstd Threads'),
fieldStyle: 'text-align: right',
emptyText: gettext('Fallback'),
minValue: 0,
cbind: {
deleteEmpty: '{!isCreate}',
},
autoEl: {
tag: 'div',
'data-qtip': gettext('With 0, half of the available cores are used'),
},
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: `${gettext('Threads used for zstd compression (non-PBS).')} ${Ext.String.format(gettext('Schema default: {0}'), 1)}`,
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'proxmoxintegerfield',
name: 'max-workers',
minValue: 1,
maxValue: 256,
fieldLabel: gettext('IO-Workers'),
fieldStyle: 'text-align: right',
emptyText: gettext('Fallback'),
cbind: {
deleteEmpty: '{!isCreate}',
},
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: `${gettext('I/O workers in the QEMU process (VMs only).')} ${Ext.String.format(gettext('Schema default: {0}'), 16)}`,
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'proxmoxcheckbox',
name: 'fleecing-enabled',
reference: 'fleecingEnabled',
fieldLabel: gettext('Fleecing'),
uncheckedValue: 0,
value: 0,
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: gettext(
'Backup write cache that can reduce IO pressure inside guests (VMs only).',
),
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'pveStorageSelector',
name: 'fleecing-storage',
fieldLabel: gettext('Fleecing Storage'),
reference: 'fleecingStorage',
clusterView: true,
storageContent: 'images',
allowBlank: false,
disabled: true,
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: gettext(
'Prefer a fast and local storage, ideally with support for discard and thin-provisioning or sparse files.',
),
},
},
{
// It's part of the 'performance' property string, so have a field to preserve the
// value, but don't expose it. It's a rather niche setting and difficult to
// convey/understand what it does.
xtype: 'proxmoxintegerfield',
name: 'pbs-entries-max',
hidden: true,
fieldLabel: 'TODO',
fieldStyle: 'text-align: right',
emptyText: 'TODO',
cbind: {
deleteEmpty: '{!isCreate}',
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'proxmoxcheckbox',
fieldLabel: gettext('Repeat missed'),
name: 'repeat-missed',
uncheckedValue: 0,
defaultValue: 0,
cbind: {
deleteDefaultValue: '{!isCreate}',
},
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: gettext(
"Run jobs as soon as possible if they couldn't start on schedule, for example, due to the node being offline.",
),
},
},
{
xtype: 'pveTwoColumnContainer',
startColumn: {
xtype: 'proxmoxKVComboBox',
fieldLabel: gettext('PBS change detection mode'),
name: 'pbs-change-detection-mode',
deleteEmpty: true,
value: '__default__',
comboItems: [
['__default__', 'Default'],
['data', 'Data'],
['metadata', 'Metadata'],
],
},
endFlex: 2,
endColumn: {
xtype: 'displayfield',
value: gettext(
'Mode to detect file changes and switch archive encoding format for container backups.',
),
},
},
{
xtype: 'component',
padding: '5 1',
html: `<span class="pmx-hint">${gettext('Note')}</span>: ${gettext(
"The node-specific 'vzdump.conf' or, if this is not set, the default from the config schema is used to determine fallback values.",
)}`,
},
],
});