]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/window/Backup.js
ui: guest import: make window wider
[pve-manager.git] / www / manager6 / window / Backup.js
1 Ext.define('PVE.window.Backup', {
2 extend: 'Ext.window.Window',
3
4 resizable: false,
5
6 initComponent: function() {
7 var me = this;
8
9 if (!me.nodename) {
10 throw "no node name specified";
11 }
12
13 if (!me.vmid) {
14 throw "no VM ID specified";
15 }
16
17 if (!me.vmtype) {
18 throw "no VM type specified";
19 }
20
21 let compressionSelector = Ext.create('PVE.form.BackupCompressionSelector', {
22 name: 'compress',
23 value: 'zstd',
24 fieldLabel: gettext('Compression'),
25 });
26
27 let modeSelector = Ext.create('PVE.form.BackupModeSelector', {
28 fieldLabel: gettext('Mode'),
29 value: 'snapshot',
30 name: 'mode',
31 });
32
33 let mailtoField = Ext.create('Ext.form.field.Text', {
34 fieldLabel: gettext('Send email to'),
35 name: 'mailto',
36 emptyText: Proxmox.Utils.noneText,
37 });
38
39 let notificationModeSelector = Ext.create({
40 xtype: 'proxmoxKVComboBox',
41 comboItems: [
42 ['auto', gettext('Auto')],
43 ['legacy-sendmail', gettext('Email (legacy)')],
44 ['notification-system', gettext('Notification system')],
45 ],
46 fieldLabel: gettext('Notification mode'),
47 name: 'notification-mode',
48 value: 'auto',
49 listeners: {
50 change: function(field, value) {
51 mailtoField.setDisabled(value === 'notification-system');
52 },
53 },
54 });
55
56 const keepNames = [
57 ['keep-last', gettext('Keep Last')],
58 ['keep-hourly', gettext('Keep Hourly')],
59 ['keep-daily', gettext('Keep Daily')],
60 ['keep-weekly', gettext('Keep Weekly')],
61 ['keep-monthly', gettext('Keep Monthly')],
62 ['keep-yearly', gettext('Keep Yearly')],
63 ];
64
65 let pruneSettings = keepNames.map(
66 name => Ext.create('Ext.form.field.Display', {
67 name: name[0],
68 fieldLabel: name[1],
69 hidden: true,
70 }),
71 );
72
73 let removeCheckbox = Ext.create('Proxmox.form.Checkbox', {
74 name: 'remove',
75 checked: false,
76 hidden: true,
77 uncheckedValue: 0,
78 fieldLabel: gettext('Prune'),
79 autoEl: {
80 tag: 'div',
81 'data-qtip': gettext('Prune older backups afterwards'),
82 },
83 handler: function(checkbox, value) {
84 pruneSettings.forEach(field => field.setHidden(!value));
85 me.down('label[name="pruneLabel"]').setHidden(!value);
86 },
87 });
88
89 let initialDefaults = false;
90
91 var storagesel = Ext.create('PVE.form.StorageSelector', {
92 nodename: me.nodename,
93 name: 'storage',
94 fieldLabel: gettext('Storage'),
95 storageContent: 'backup',
96 allowBlank: false,
97 listeners: {
98 change: function(f, v) {
99 if (!initialDefaults) {
100 me.setLoading(false);
101 }
102
103 if (v === null || v === undefined || v === '') {
104 return;
105 }
106
107 let store = f.getStore();
108 let rec = store.findRecord('storage', v, 0, false, true, true);
109
110 if (rec && rec.data && rec.data.type === 'pbs') {
111 compressionSelector.setValue('zstd');
112 compressionSelector.setDisabled(true);
113 } else if (!compressionSelector.getEditable()) {
114 compressionSelector.setDisabled(false);
115 }
116
117 Proxmox.Utils.API2Request({
118 url: `/nodes/${me.nodename}/vzdump/defaults`,
119 method: 'GET',
120 params: {
121 storage: v,
122 },
123 waitMsgTarget: me,
124 success: function(response, opts) {
125 const data = response.result.data;
126
127 if (!initialDefaults && data.mailto !== undefined) {
128 mailtoField.setValue(data.mailto);
129 }
130 if (!initialDefaults && data['notification-mode'] !== undefined) {
131 notificationModeSelector.setValue(data['notification-mode']);
132 }
133 if (!initialDefaults && data.mode !== undefined) {
134 modeSelector.setValue(data.mode);
135 }
136 if (!initialDefaults && (data['notes-template'] ?? false)) {
137 me.down('field[name=notes-template]').setValue(
138 PVE.Utils.unEscapeNotesTemplate(data['notes-template']),
139 );
140 }
141
142 initialDefaults = true;
143
144 // always update storage dependent properties
145 if (data['prune-backups'] !== undefined) {
146 const keepParams = PVE.Parser.parsePropertyString(
147 data["prune-backups"],
148 );
149 if (!keepParams['keep-all']) {
150 removeCheckbox.setHidden(false);
151 pruneSettings.forEach(function(field) {
152 const keep = keepParams[field.name];
153 if (keep) {
154 field.setValue(keep);
155 } else {
156 field.reset();
157 }
158 });
159 return;
160 }
161 }
162
163 // no defaults or keep-all=1
164 removeCheckbox.setHidden(true);
165 removeCheckbox.setValue(false);
166 pruneSettings.forEach(field => field.reset());
167 },
168 failure: function(response, opts) {
169 initialDefaults = true;
170
171 removeCheckbox.setHidden(true);
172 removeCheckbox.setValue(false);
173 pruneSettings.forEach(field => field.reset());
174
175 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
176 },
177 });
178 },
179 },
180 });
181
182 let protectedCheckbox = Ext.create('Proxmox.form.Checkbox', {
183 name: 'protected',
184 checked: false,
185 uncheckedValue: 0,
186 fieldLabel: gettext('Protected'),
187 });
188
189 me.formPanel = Ext.create('Proxmox.panel.InputPanel', {
190 bodyPadding: 10,
191 border: false,
192 column1: [
193 storagesel,
194 modeSelector,
195 protectedCheckbox,
196 ],
197 column2: [
198 compressionSelector,
199 notificationModeSelector,
200 mailtoField,
201 removeCheckbox,
202 ],
203 columnB: [
204 {
205 xtype: 'textareafield',
206 name: 'notes-template',
207 fieldLabel: gettext('Notes'),
208 anchor: '100%',
209 value: '{{guestname}}',
210 },
211 {
212 xtype: 'box',
213 style: {
214 margin: '8px 0px',
215 'line-height': '1.5em',
216 },
217 html: Ext.String.format(
218 gettext('Possible template variables are: {0}'),
219 PVE.Utils.notesTemplateVars.map(v => `<code>{{${v}}}</code>`).join(', '),
220 ),
221 },
222 {
223 xtype: 'label',
224 name: 'pruneLabel',
225 text: gettext('Storage Retention Configuration') + ':',
226 hidden: true,
227 },
228 {
229 layout: 'hbox',
230 border: false,
231 defaults: {
232 border: false,
233 layout: 'anchor',
234 flex: 1,
235 },
236 items: [
237 {
238 padding: '0 10 0 0',
239 defaults: {
240 labelWidth: 110,
241 },
242 items: [
243 pruneSettings[0],
244 pruneSettings[2],
245 pruneSettings[4],
246 ],
247 },
248 {
249 padding: '0 0 0 10',
250 defaults: {
251 labelWidth: 110,
252 },
253 items: [
254 pruneSettings[1],
255 pruneSettings[3],
256 pruneSettings[5],
257 ],
258 },
259 ],
260 },
261 ],
262 });
263
264 var submitBtn = Ext.create('Ext.Button', {
265 text: gettext('Backup'),
266 handler: function() {
267 var storage = storagesel.getValue();
268 let values = me.formPanel.getValues();
269 var params = {
270 storage: storage,
271 vmid: me.vmid,
272 mode: values.mode,
273 remove: values.remove,
274 };
275
276 if (values.mailto) {
277 params.mailto = values.mailto;
278 }
279
280 if (values['notification-mode']) {
281 params['notification-mode'] = values['notification-mode'];
282 }
283
284 if (values.compress) {
285 params.compress = values.compress;
286 }
287
288 if (values.protected) {
289 params.protected = values.protected;
290 }
291
292 if (values['notes-template']) {
293 params['notes-template'] = PVE.Utils.escapeNotesTemplate(
294 values['notes-template']);
295 }
296
297 Proxmox.Utils.API2Request({
298 url: '/nodes/' + me.nodename + '/vzdump',
299 params: params,
300 method: 'POST',
301 failure: function(response, opts) {
302 Ext.Msg.alert('Error', response.htmlStatus);
303 },
304 success: function(response, options) {
305 // close later so we reload the grid
306 // after the task has completed
307 me.hide();
308
309 var upid = response.result.data;
310
311 var win = Ext.create('Proxmox.window.TaskViewer', {
312 upid: upid,
313 listeners: {
314 close: function() {
315 me.close();
316 },
317 },
318 });
319 win.show();
320 },
321 });
322 },
323 });
324
325 var helpBtn = Ext.create('Proxmox.button.Help', {
326 onlineHelp: 'chapter_vzdump',
327 listenToGlobalEvent: false,
328 hidden: false,
329 });
330
331 var title = gettext('Backup') + " " +
332 (me.vmtype === 'lxc' ? "CT" : "VM") +
333 " " + me.vmid;
334
335 Ext.apply(me, {
336 title: title,
337 modal: true,
338 layout: 'auto',
339 border: false,
340 width: 600,
341 items: [me.formPanel],
342 buttons: [helpBtn, '->', submitBtn],
343 listeners: {
344 afterrender: function() {
345 /// cleared within the storage selector's change listener
346 me.setLoading(gettext('Please wait...'));
347 storagesel.setValue(me.storage);
348 },
349 },
350 });
351
352 me.callParent();
353 },
354 });