]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/panel/BackupAdvancedOptions.js
ui: backup job: allow to set up fleecing for a job in advanced config
[pve-manager.git] / www / manager6 / panel / BackupAdvancedOptions.js
CommitLineData
bb4741c7
FE
1/*
2 * Input panel for advanced backup options intended to be used as part of an edit/create window.
3 */
4Ext.define('PVE.panel.BackupAdvancedOptions', {
5 extend: 'Proxmox.panel.InputPanel',
6 xtype: 'pveBackupAdvancedOptionsPanel',
7 mixins: ['Proxmox.Mixin.CBind'],
8
9 cbindData: function() {
10 let me = this;
11 me.isCreate = !!me.isCreate;
12 return {};
13 },
14
6b3dddb0
TL
15 viewModel: {
16 data: {},
17 },
18
9f2b84be
FE
19 controller: {
20 xclass: 'Ext.app.ViewController',
21 },
22
bb4741c7 23 onGetValues: function(formValues) {
249ac8aa
TL
24 let me = this;
25 if (me.needMask) { // isMasked() may not yet be true if not rendered once
bb4741c7
FE
26 return {};
27 }
28
249ac8aa
TL
29 let options = {};
30
31 if (!me.isCreate) {
32 options.delete = []; // to avoid having to check this all the time
33 }
34 const deletePropertyOnEdit = me.isCreate
35 ? () => { /* no-op on create */ }
36 : key => options.delete.push(key);
bb4741c7 37
6b3dddb0 38 let fleecing = {}, fleecingOptions = ['fleecing-enabled', 'fleecing-storage'];
249ac8aa 39 let performance = {}, performanceOptions = ['max-workers', 'pbs-entries-max'];
bb4741c7
FE
40
41 for (const [key, value] of Object.entries(formValues)) {
42 if (performanceOptions.includes(key)) {
43 performance[key] = value;
44 // deleteEmpty is not currently implemented for pveBandwidthField
45 } else if (key === 'bwlimit' && value === '') {
249ac8aa 46 deletePropertyOnEdit('bwlimit');
bb4741c7
FE
47 } else if (key === 'delete') {
48 if (Array.isArray(value)) {
49 value.filter(opt => !performanceOptions.includes(opt)).forEach(
249ac8aa 50 opt => deletePropertyOnEdit(opt),
bb4741c7
FE
51 );
52 } else if (!performanceOptions.includes(formValues.delete)) {
249ac8aa 53 deletePropertyOnEdit(value);
bb4741c7 54 }
6b3dddb0
TL
55 } else if (fleecingOptions.includes(key)) {
56 let fleecingKey = key.slice('fleecing-'.length);
57 fleecing[fleecingKey] = value;
bb4741c7
FE
58 } else {
59 options[key] = value;
60 }
61 }
62
63 if (Object.keys(performance).length > 0) {
64 options.performance = PVE.Parser.printPropertyString(performance);
65 } else {
249ac8aa 66 deletePropertyOnEdit('performance');
bb4741c7
FE
67 }
68
6b3dddb0
TL
69 if (Object.keys(fleecing).length > 0) {
70 options.fleecing = PVE.Parser.printPropertyString(fleecing);
71 } else {
72 deletePropertyOnEdit('fleecing');
73 }
74
75 if (me.isCreate) {
76 delete options.delete;
77 }
78
bb4741c7
FE
79 return options;
80 },
81
6b3dddb0
TL
82 onSetValues: function(values) {
83 if (values.fleecing) {
84 for (const [key, value] of Object.entries(values.fleecing)) {
85 values[`fleecing-${key}`] = value;
86 }
87 delete values.fleecing;
88 }
89 return values;
90 },
91
9f2b84be 92 updateCompression: function(value, disabled) {
dddcfc2e 93 this.lookup('zstdThreadCount').setDisabled(disabled || value !== 'zstd');
9f2b84be
FE
94 },
95
9486317c 96 items: [
bb4741c7 97 {
9486317c
DC
98 xtype: 'pveTwoColumnContainer',
99 startColumn: {
100 xtype: 'pveBandwidthField',
101 name: 'bwlimit',
102 fieldLabel: gettext('Bandwidth Limit'),
9e917dd7 103 emptyText: gettext('Fallback'),
9486317c
DC
104 backendUnit: 'KiB',
105 allowZero: true,
106 emptyValue: '',
107 autoEl: {
108 tag: 'div',
109 'data-qtip': Ext.String.format(gettext('Use {0} for unlimited'), 0),
110 },
111 },
112 endFlex: 2,
113 endColumn: {
114 xtype: 'displayfield',
9e917dd7 115 value: `${gettext('Limit I/O bandwidth.')} ${Ext.String.format(gettext("Schema default: {0}"), 0)}`,
bb4741c7
FE
116 },
117 },
118 {
9486317c
DC
119 xtype: 'pveTwoColumnContainer',
120 startColumn: {
121 xtype: 'proxmoxintegerfield',
122 name: 'zstd',
123 reference: 'zstdThreadCount',
124 fieldLabel: Ext.String.format(gettext('{0} Threads'), 'Zstd'),
125 fieldStyle: 'text-align: right',
9e917dd7 126 emptyText: gettext('Fallback'),
9486317c
DC
127 minValue: 0,
128 cbind: {
129 deleteEmpty: '{!isCreate}',
130 },
131 autoEl: {
132 tag: 'div',
133 'data-qtip': gettext('With 0, half of the available cores are used'),
134 },
bb4741c7 135 },
9486317c
DC
136 endFlex: 2,
137 endColumn: {
138 xtype: 'displayfield',
9e917dd7 139 value: `${gettext('Threads used for zstd compression (non-PBS).')} ${Ext.String.format(gettext("Schema default: {0}"), 1)}`,
bb4741c7
FE
140 },
141 },
142 {
9486317c
DC
143 xtype: 'pveTwoColumnContainer',
144 startColumn: {
145 xtype: 'proxmoxintegerfield',
146 name: 'max-workers',
147 minValue: 1,
148 maxValue: 256,
149 fieldLabel: gettext('IO-Workers'),
150 fieldStyle: 'text-align: right',
9e917dd7 151 emptyText: gettext('Fallback'),
9486317c
DC
152 cbind: {
153 deleteEmpty: '{!isCreate}',
154 },
155 },
156 endFlex: 2,
157 endColumn: {
158 xtype: 'displayfield',
9e917dd7 159 value: `${gettext('I/O workers in the QEMU process (VMs only).')} ${Ext.String.format(gettext("Schema default: {0}"), 16)}`,
bb4741c7
FE
160 },
161 },
6b3dddb0
TL
162 {
163 xtype: 'pveTwoColumnContainer',
164 startColumn: {
165 xtype: 'proxmoxcheckbox',
166 name: 'fleecing-enabled',
167 reference: 'fleecingEnabled',
168 fieldLabel: gettext('Fleecing'),
169 uncheckedValue: 0,
170 value: 0,
171 },
172 endFlex: 2,
173 endColumn: {
174 xtype: 'displayfield',
175 value: gettext('Backup write cache that can reduce IO pressure inside guests (VMs only).'),
176 },
177 },
178 {
179 xtype: 'pveTwoColumnContainer',
180 startColumn: {
181 xtype: 'pveStorageSelector',
182 name: 'fleecing-storage',
183 fieldLabel: gettext('Fleecing Storage'),
184 reference: 'storageSelector',
185 clusterView: true,
186 storageContent: 'images',
187 allowBlank: false,
188 bind: {
189 disabled: '{!fleecingEnabled.checked}',
190 },
191 },
192 endFlex: 2,
193 endColumn: {
194 xtype: 'displayfield',
195 value: gettext('Prefer a fast and local storage, ideally with support for discard and thin-provisioning or sparse files.'),
196 },
197 },
bb4741c7
FE
198 {
199 // It's part of the 'performance' property string, so have a field to preserve the
200 // value, but don't expose it. It's a rather niche setting and difficult to
201 // convey/understand what it does.
202 xtype: 'proxmoxintegerfield',
203 name: 'pbs-entries-max',
204 hidden: true,
205 fieldLabel: 'TODO',
206 fieldStyle: 'text-align: right',
5abdd1e4 207 emptyText: 'TODO',
bb4741c7
FE
208 cbind: {
209 deleteEmpty: '{!isCreate}',
210 },
211 },
1d777a46 212 {
9486317c
DC
213 xtype: 'pveTwoColumnContainer',
214 startColumn: {
215 xtype: 'proxmoxcheckbox',
216 fieldLabel: gettext('Repeat missed'),
217 name: 'repeat-missed',
218 uncheckedValue: 0,
219 defaultValue: 0,
220 cbind: {
221 deleteDefaultValue: '{!isCreate}',
222 },
223 },
224 endFlex: 2,
225 endColumn: {
226 xtype: 'displayfield',
227 value: gettext("Run jobs as soon as possible if they couldn't start on schedule, for example, due to the node being offline."),
1d777a46
FE
228 },
229 },
bb4741c7
FE
230 {
231 xtype: 'component',
bb4741c7 232 padding: '5 1',
a32a5c4a 233 html: `<span class="pmx-hint">${gettext('Note')}</span>: ${
9e917dd7 234 gettext("The node-specific 'vzdump.conf' or, if this is not set, the default from the config schema is used to determine fallback values.")}`,
bb4741c7
FE
235 },
236 ],
237});