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