]>
Commit | Line | Data |
---|---|---|
ad74d86c | 1 | Ext.define('PVE.dc.BackupEdit', { |
9fccc702 | 2 | extend: 'Proxmox.window.Edit', |
ad74d86c DM |
3 | alias: ['widget.pveDcBackupEdit'], |
4 | ||
fc03fcb8 TL |
5 | defaultFocus: undefined, |
6 | ||
ad74d86c | 7 | initComponent : function() { |
ad74d86c DM |
8 | var me = this; |
9 | ||
d5e771ce | 10 | me.isCreate = !me.jobid; |
ad74d86c DM |
11 | |
12 | var url; | |
13 | var method; | |
14 | ||
d5e771ce | 15 | if (me.isCreate) { |
ad74d86c DM |
16 | url = '/api2/extjs/cluster/backup'; |
17 | method = 'POST'; | |
18 | } else { | |
19 | url = '/api2/extjs/cluster/backup/' + me.jobid; | |
20 | method = 'PUT'; | |
21 | } | |
22 | ||
23 | var vmidField = Ext.create('Ext.form.field.Hidden', { | |
24 | name: 'vmid' | |
25 | }); | |
26 | ||
d5e771ce EK |
27 | /*jslint confusion: true*/ |
28 | // 'value' can be assigned a string or an array | |
09cacce7 TL |
29 | var selModeField = Ext.create('Proxmox.form.KVComboBox', { |
30 | xtype: 'proxmoxKVComboBox', | |
a26c8bf7 | 31 | comboItems: [ |
ad74d86c DM |
32 | ['include', gettext('Include selected VMs')], |
33 | ['all', gettext('All')], | |
ab648869 | 34 | ['exclude', gettext('Exclude selected VMs')], |
a82afef0 | 35 | ['pool', gettext('Pool based')] |
ad74d86c DM |
36 | ], |
37 | fieldLabel: gettext('Selection mode'), | |
38 | name: 'selMode', | |
39 | value: '' | |
40 | }); | |
41 | ||
ad74d86c DM |
42 | var sm = Ext.create('Ext.selection.CheckboxModel', { |
43 | mode: 'SIMPLE', | |
44 | listeners: { | |
45 | selectionchange: function(model, selected) { | |
be8b69aa TL |
46 | var sel = []; |
47 | Ext.Array.each(selected, function(record) { | |
48 | sel.push(record.data.vmid); | |
49 | }); | |
50 | ||
51 | // to avoid endless recursion suspend the vmidField change | |
52 | // event temporary as it calls us again | |
53 | vmidField.suspendEvent('change'); | |
54 | vmidField.setValue(sel); | |
55 | vmidField.resumeEvent('change'); | |
ad74d86c DM |
56 | } |
57 | } | |
58 | }); | |
59 | ||
60 | var storagesel = Ext.create('PVE.form.StorageSelector', { | |
61 | fieldLabel: gettext('Storage'), | |
62 | nodename: 'localhost', | |
63 | storageContent: 'backup', | |
64 | allowBlank: false, | |
65 | name: 'storage' | |
66 | }); | |
67 | ||
68 | var store = new Ext.data.Store({ | |
69 | model: 'PVEResources', | |
60e049c2 TM |
70 | sorters: { |
71 | property: 'vmid', | |
72 | order: 'ASC' | |
ad74d86c DM |
73 | } |
74 | }); | |
75 | ||
76 | var vmgrid = Ext.createWidget('grid', { | |
77 | store: store, | |
78 | border: true, | |
79 | height: 300, | |
80 | selModel: sm, | |
81 | disabled: true, | |
82 | columns: [ | |
60e049c2 | 83 | { |
ad74d86c DM |
84 | header: 'ID', |
85 | dataIndex: 'vmid', | |
86 | width: 60 | |
87 | }, | |
60e049c2 | 88 | { |
ad74d86c DM |
89 | header: gettext('Node'), |
90 | dataIndex: 'node' | |
91 | }, | |
60e049c2 | 92 | { |
ad74d86c DM |
93 | header: gettext('Status'), |
94 | dataIndex: 'uptime', | |
95 | renderer: function(value) { | |
96 | if (value) { | |
e7ade592 | 97 | return Proxmox.Utils.runningText; |
ad74d86c | 98 | } else { |
e7ade592 | 99 | return Proxmox.Utils.stoppedText; |
ad74d86c DM |
100 | } |
101 | } | |
102 | }, | |
60e049c2 TM |
103 | { |
104 | header: gettext('Name'), | |
ad74d86c | 105 | dataIndex: 'name', |
60e049c2 | 106 | flex: 1 |
ad74d86c | 107 | }, |
60e049c2 TM |
108 | { |
109 | header: gettext('Type'), | |
ad74d86c DM |
110 | dataIndex: 'type' |
111 | } | |
112 | ] | |
113 | }); | |
114 | ||
ab648869 TM |
115 | var selectPoolMembers = function(poolid) { |
116 | if (!poolid) { | |
117 | return; | |
118 | } | |
119 | sm.deselectAll(true); | |
120 | store.filter([ | |
121 | { | |
122 | id: 'poolFilter', | |
123 | property: 'pool', | |
124 | value: poolid | |
125 | } | |
126 | ]); | |
127 | sm.selectAll(true); | |
128 | }; | |
129 | ||
130 | var selPool = Ext.create('PVE.form.PoolSelector', { | |
a82afef0 | 131 | fieldLabel: gettext('Pool to backup'), |
ab648869 TM |
132 | hidden: true, |
133 | allowBlank: true, | |
134 | name: 'pool', | |
135 | listeners: { | |
136 | change: function( selpool, newValue, oldValue) { | |
137 | selectPoolMembers(newValue); | |
138 | } | |
139 | } | |
140 | }); | |
141 | ||
ad74d86c DM |
142 | var nodesel = Ext.create('PVE.form.NodeSelector', { |
143 | name: 'node', | |
144 | fieldLabel: gettext('Node'), | |
145 | allowBlank: true, | |
146 | editable: true, | |
147 | autoSelect: false, | |
148 | emptyText: '-- ' + gettext('All') + ' --', | |
149 | listeners: { | |
150 | change: function(f, value) { | |
151 | storagesel.setNodename(value || 'localhost'); | |
152 | var mode = selModeField.getValue(); | |
153 | store.clearFilter(); | |
154 | store.filterBy(function(rec) { | |
155 | return (!value || rec.get('node') === value); | |
156 | }); | |
157 | if (mode === 'all') { | |
158 | sm.selectAll(true); | |
159 | } | |
ab648869 TM |
160 | |
161 | if (mode === 'pool') { | |
162 | selectPoolMembers(selPool.value); | |
163 | } | |
ad74d86c DM |
164 | } |
165 | } | |
166 | }); | |
167 | ||
168 | var column1 = [ | |
169 | nodesel, | |
170 | storagesel, | |
171 | { | |
172 | xtype: 'pveDayOfWeekSelector', | |
173 | name: 'dow', | |
174 | fieldLabel: gettext('Day of week'), | |
175 | multiSelect: true, | |
176 | value: ['sat'], | |
177 | allowBlank: false | |
178 | }, | |
179 | { | |
180 | xtype: 'timefield', | |
181 | fieldLabel: gettext('Start Time'), | |
182 | name: 'starttime', | |
183 | format: 'H:i', | |
4ecd1d07 | 184 | formatText: 'HH:MM', |
ad74d86c DM |
185 | value: '00:00', |
186 | allowBlank: false | |
187 | }, | |
ab648869 TM |
188 | selModeField, |
189 | selPool | |
ad74d86c DM |
190 | ]; |
191 | ||
192 | var column2 = [ | |
193 | { | |
194 | xtype: 'textfield', | |
195 | fieldLabel: gettext('Send email to'), | |
196 | name: 'mailto' | |
197 | }, | |
198 | { | |
199 | xtype: 'pveEmailNotificationSelector', | |
200 | fieldLabel: gettext('Email notification'), | |
201 | name: 'mailnotification', | |
d5e771ce EK |
202 | deleteEmpty: me.isCreate ? false : true, |
203 | value: me.isCreate ? 'always' : '' | |
ad74d86c DM |
204 | }, |
205 | { | |
206 | xtype: 'pveCompressionSelector', | |
207 | fieldLabel: gettext('Compression'), | |
208 | name: 'compress', | |
d5e771ce | 209 | deleteEmpty: me.isCreate ? false : true, |
be37a97e | 210 | value: 'lzo' |
ad74d86c DM |
211 | }, |
212 | { | |
213 | xtype: 'pveBackupModeSelector', | |
214 | fieldLabel: gettext('Mode'), | |
215 | value: 'snapshot', | |
216 | name: 'mode' | |
217 | }, | |
cfdc7ada | 218 | { |
896c0d50 | 219 | xtype: 'proxmoxcheckbox', |
cfdc7ada EK |
220 | fieldLabel: gettext('Enable'), |
221 | name: 'enabled', | |
222 | uncheckedValue: 0, | |
223 | defaultValue: 1, | |
224 | checked: true | |
225 | }, | |
ad74d86c DM |
226 | vmidField |
227 | ]; | |
d5e771ce | 228 | /*jslint confusion: false*/ |
ad74d86c | 229 | |
ef4ef788 | 230 | var ipanel = Ext.create('Proxmox.panel.InputPanel', { |
0de33b54 | 231 | onlineHelp: 'chapter_vzdump', |
ad74d86c DM |
232 | column1: column1, |
233 | column2: column2, | |
234 | onGetValues: function(values) { | |
235 | if (!values.node) { | |
d5e771ce | 236 | if (!me.isCreate) { |
60e049c2 | 237 | Proxmox.Utils.assemble_field_data(values, { 'delete': 'node' }); |
ad74d86c DM |
238 | } |
239 | delete values.node; | |
240 | } | |
241 | ||
242 | var selMode = values.selMode; | |
243 | delete values.selMode; | |
244 | ||
245 | if (selMode === 'all') { | |
246 | values.all = 1; | |
247 | values.exclude = ''; | |
248 | delete values.vmid; | |
249 | } else if (selMode === 'exclude') { | |
250 | values.all = 1; | |
251 | values.exclude = values.vmid; | |
252 | delete values.vmid; | |
ab648869 TM |
253 | } else if (selMode === 'pool') { |
254 | delete values.vmid; | |
255 | } | |
256 | ||
257 | if (selMode !== 'pool') { | |
258 | delete values.pool; | |
ad74d86c DM |
259 | } |
260 | return values; | |
261 | } | |
262 | }); | |
263 | ||
264 | var update_vmid_selection = function(list, mode) { | |
ab648869 | 265 | if (mode !== 'all' && mode !== 'pool') { |
ad74d86c DM |
266 | sm.deselectAll(true); |
267 | if (list) { | |
268 | Ext.Array.each(list.split(','), function(vmid) { | |
269 | var rec = store.findRecord('vmid', vmid); | |
270 | if (rec) { | |
271 | sm.select(rec, true); | |
272 | } | |
273 | }); | |
274 | } | |
275 | } | |
ad74d86c DM |
276 | }; |
277 | ||
278 | vmidField.on('change', function(f, value) { | |
279 | var mode = selModeField.getValue(); | |
280 | update_vmid_selection(value, mode); | |
281 | }); | |
282 | ||
283 | selModeField.on('change', function(f, value, oldValue) { | |
ab648869 TM |
284 | if (oldValue === 'pool') { |
285 | store.removeFilter('poolFilter'); | |
286 | } | |
287 | ||
288 | if (oldValue === 'all') { | |
289 | sm.deselectAll(true); | |
290 | vmidField.setValue(''); | |
291 | } | |
292 | ||
ad74d86c DM |
293 | if (value === 'all') { |
294 | sm.selectAll(true); | |
295 | vmgrid.setDisabled(true); | |
296 | } else { | |
297 | vmgrid.setDisabled(false); | |
298 | } | |
ab648869 TM |
299 | |
300 | if (value === 'pool') { | |
301 | vmgrid.setDisabled(true); | |
ad74d86c | 302 | vmidField.setValue(''); |
ab648869 TM |
303 | selPool.setVisible(true); |
304 | selPool.allowBlank = false; | |
305 | selectPoolMembers(selPool.value); | |
306 | ||
307 | } else { | |
308 | selPool.setVisible(false); | |
309 | selPool.allowBlank = true; | |
ad74d86c DM |
310 | } |
311 | var list = vmidField.getValue(); | |
312 | update_vmid_selection(list, value); | |
313 | }); | |
60e049c2 | 314 | |
ad74d86c DM |
315 | var reload = function() { |
316 | store.load({ | |
317 | params: { type: 'vm' }, | |
318 | callback: function() { | |
319 | var node = nodesel.getValue(); | |
320 | store.clearFilter(); | |
321 | store.filterBy(function(rec) { | |
163bf378 | 322 | return (!node || node.length === 0 || rec.get('node') === node); |
ad74d86c DM |
323 | }); |
324 | var list = vmidField.getValue(); | |
325 | var mode = selModeField.getValue(); | |
326 | if (mode === 'all') { | |
327 | sm.selectAll(true); | |
ab648869 TM |
328 | } else if (mode === 'pool'){ |
329 | selectPoolMembers(selPool.value); | |
ad74d86c DM |
330 | } else { |
331 | update_vmid_selection(list, mode); | |
332 | } | |
333 | } | |
334 | }); | |
335 | }; | |
336 | ||
337 | Ext.applyIf(me, { | |
338 | subject: gettext("Backup Job"), | |
339 | url: url, | |
340 | method: method, | |
341 | items: [ ipanel, vmgrid ] | |
342 | }); | |
343 | ||
344 | me.callParent(); | |
345 | ||
d5e771ce | 346 | if (me.isCreate) { |
ad74d86c DM |
347 | selModeField.setValue('include'); |
348 | } else { | |
349 | me.load({ | |
350 | success: function(response, options) { | |
351 | var data = response.result.data; | |
352 | ||
353 | data.dow = data.dow.split(','); | |
354 | ||
355 | if (data.all || data.exclude) { | |
356 | if (data.exclude) { | |
357 | data.vmid = data.exclude; | |
358 | data.selMode = 'exclude'; | |
359 | } else { | |
360 | data.vmid = ''; | |
361 | data.selMode = 'all'; | |
362 | } | |
ab648869 TM |
363 | } else if (data.pool) { |
364 | data.selMode = 'pool'; | |
365 | data.selPool = data.pool; | |
ad74d86c DM |
366 | } else { |
367 | data.selMode = 'include'; | |
368 | } | |
369 | ||
370 | me.setValues(data); | |
371 | } | |
372 | }); | |
373 | } | |
374 | ||
375 | reload(); | |
376 | } | |
377 | }); | |
378 | ||
379 | ||
380 | Ext.define('PVE.dc.BackupView', { | |
381 | extend: 'Ext.grid.GridPanel', | |
382 | ||
383 | alias: ['widget.pveDcBackupView'], | |
384 | ||
ba93a9c6 DC |
385 | onlineHelp: 'chapter_vzdump', |
386 | ||
ad74d86c DM |
387 | allText: '-- ' + gettext('All') + ' --', |
388 | allExceptText: gettext('All except {0}'), | |
389 | ||
390 | initComponent : function() { | |
391 | var me = this; | |
392 | ||
393 | var store = new Ext.data.Store({ | |
394 | model: 'pve-cluster-backup', | |
395 | proxy: { | |
56a353b9 | 396 | type: 'proxmox', |
ad74d86c DM |
397 | url: "/api2/json/cluster/backup" |
398 | } | |
399 | }); | |
400 | ||
401 | var reload = function() { | |
402 | store.load(); | |
403 | }; | |
404 | ||
405 | var sm = Ext.create('Ext.selection.RowModel', {}); | |
406 | ||
407 | var run_editor = function() { | |
408 | var rec = sm.getSelection()[0]; | |
409 | if (!rec) { | |
410 | return; | |
411 | } | |
412 | ||
43b2494b SR |
413 | var win = Ext.create('PVE.dc.BackupEdit', { |
414 | jobid: rec.data.id | |
415 | }); | |
416 | win.on('destroy', reload); | |
417 | win.show(); | |
ad74d86c DM |
418 | }; |
419 | ||
389d3cf1 SR |
420 | var run_backup_now = function(job) { |
421 | job = Ext.clone(job); | |
422 | ||
423 | var allNodes = PVE.data.ResourceStore.getNodes(); | |
424 | var jobNode = job.node; | |
425 | ||
426 | // Remove properties related to scheduling | |
427 | delete job.enabled; | |
428 | delete job.starttime; | |
429 | delete job.dow; | |
430 | delete job.id; | |
431 | delete job.node; | |
432 | job.all = job.all === true ? 1 : 0; | |
433 | ||
434 | var errors = []; | |
435 | var inProgress = allNodes.length; | |
436 | ||
437 | Ext.Msg.show({ | |
438 | title: gettext('Please wait...'), | |
439 | closable: false, | |
440 | progress: true | |
441 | }); | |
442 | Ext.Msg.updateProgress(0, '0/' + allNodes.length); | |
443 | ||
444 | var postRequest = function () { | |
445 | inProgress++; | |
446 | ||
447 | Ext.Msg.updateProgress(inProgress/allNodes.length, | |
448 | inProgress + '/' + allNodes.length); | |
449 | ||
450 | if (inProgress == allNodes.length) { | |
451 | Ext.Msg.hide(); | |
452 | if (errors !== undefined && errors.length > 0) { | |
453 | Ext.Msg.alert('Error', 'Some errors have been encountered:<br />---<br />' | |
454 | + errors.join('<br />---<br />')); | |
455 | } | |
456 | } | |
457 | } | |
458 | ||
459 | allNodes.forEach(node => { | |
460 | if (node.status !== 'online' || | |
461 | (jobNode !== undefined && jobNode !== node.node)) { | |
462 | errors.push(node.node + ": " + gettext("Node is offline")); | |
463 | return; | |
464 | } | |
465 | ||
466 | inProgress--; | |
467 | ||
468 | Proxmox.Utils.API2Request({ | |
469 | url: '/nodes/' + node.node + '/vzdump', | |
470 | method: 'POST', | |
471 | params: job, | |
472 | failure: function (response, opts) { | |
473 | errors.push(node.node + ': ' + response.htmlStatus); | |
474 | postRequest(); | |
475 | }, | |
476 | success: postRequest | |
477 | }); | |
478 | }); | |
479 | } | |
480 | ||
5720fafa | 481 | var edit_btn = new Proxmox.button.Button({ |
ad74d86c DM |
482 | text: gettext('Edit'), |
483 | disabled: true, | |
484 | selModel: sm, | |
485 | handler: run_editor | |
486 | }); | |
487 | ||
389d3cf1 SR |
488 | var run_btn = new Proxmox.button.Button({ |
489 | text: gettext('Run now'), | |
490 | disabled: true, | |
491 | selModel: sm, | |
492 | handler: function() { | |
493 | var rec = sm.getSelection()[0]; | |
494 | if (!rec) { | |
495 | return; | |
496 | } | |
497 | ||
498 | Ext.Msg.show({ | |
499 | title: gettext('Confirm'), | |
500 | icon: Ext.Msg.QUESTION, | |
501 | msg: gettext('Start the selected backup job now?'), | |
502 | buttons: Ext.Msg.YESNO, | |
503 | callback: function(btn) { | |
504 | if (btn !== 'yes') { | |
505 | return; | |
506 | } | |
507 | run_backup_now(rec.data); | |
508 | } | |
509 | }); | |
510 | } | |
511 | }); | |
512 | ||
3b1ca3ff | 513 | var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', { |
ad74d86c | 514 | selModel: sm, |
3b1ca3ff DC |
515 | baseurl: '/cluster/backup', |
516 | callback: function() { | |
517 | reload(); | |
ad74d86c DM |
518 | } |
519 | }); | |
520 | ||
e7ade592 | 521 | Proxmox.Utils.monStoreErrors(me, store); |
ad74d86c DM |
522 | |
523 | Ext.apply(me, { | |
524 | store: store, | |
525 | selModel: sm, | |
c4bb9405 DC |
526 | stateful: true, |
527 | stateId: 'grid-dc-backup', | |
ad74d86c DM |
528 | viewConfig: { |
529 | trackOver: false | |
530 | }, | |
531 | tbar: [ | |
532 | { | |
533 | text: gettext('Add'), | |
534 | handler: function() { | |
535 | var win = Ext.create('PVE.dc.BackupEdit',{}); | |
536 | win.on('destroy', reload); | |
537 | win.show(); | |
538 | } | |
539 | }, | |
540 | remove_btn, | |
389d3cf1 SR |
541 | edit_btn, |
542 | run_btn | |
60e049c2 | 543 | ], |
ad74d86c | 544 | columns: [ |
cfdc7ada EK |
545 | { |
546 | header: gettext('Enabled'), | |
ae9e2161 | 547 | width: 80, |
cfdc7ada | 548 | dataIndex: 'enabled', |
370ed4c8 | 549 | xtype: 'checkcolumn', |
cfdc7ada | 550 | sortable: true, |
370ed4c8 DC |
551 | disabled: true, |
552 | disabledCls: 'x-item-enabled', | |
22f2f9d6 | 553 | stopSelection: false |
cfdc7ada | 554 | }, |
ad74d86c DM |
555 | { |
556 | header: gettext('Node'), | |
557 | width: 100, | |
558 | sortable: true, | |
559 | dataIndex: 'node', | |
560 | renderer: function(value) { | |
561 | if (value) { | |
562 | return value; | |
563 | } | |
564 | return me.allText; | |
565 | } | |
566 | }, | |
567 | { | |
568 | header: gettext('Day of week'), | |
569 | width: 200, | |
570 | sortable: false, | |
2bdf9dd3 DC |
571 | dataIndex: 'dow', |
572 | renderer: function(val) { | |
573 | var dows = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; | |
574 | var selected = []; | |
af3838c5 | 575 | var cur = -1; |
2bdf9dd3 | 576 | val.split(',').forEach(function(day){ |
af3838c5 | 577 | cur++; |
68f8c765 | 578 | var dow = (dows.indexOf(day)+6)%7; |
af3838c5 DC |
579 | if (cur === dow) { |
580 | if (selected.length === 0 || selected[selected.length-1] === 0) { | |
581 | selected.push(1); | |
582 | } else { | |
583 | selected[selected.length-1]++; | |
584 | } | |
585 | } else { | |
586 | while (cur < dow) { | |
587 | cur++; | |
588 | selected.push(0); | |
589 | } | |
590 | selected.push(1); | |
591 | } | |
2bdf9dd3 | 592 | }); |
af3838c5 DC |
593 | |
594 | cur = -1; | |
595 | var days = []; | |
596 | selected.forEach(function(item) { | |
597 | cur++; | |
598 | if (item > 2) { | |
599 | days.push(Ext.Date.dayNames[(cur+1)] + '-' + Ext.Date.dayNames[(cur+item)%7]); | |
600 | cur += item-1; | |
601 | } else if (item == 2) { | |
602 | days.push(Ext.Date.dayNames[cur+1]); | |
603 | days.push(Ext.Date.dayNames[(cur+2)%7]); | |
604 | cur++; | |
605 | } else if (item == 1) { | |
606 | days.push(Ext.Date.dayNames[(cur+1)%7]); | |
607 | } | |
a764c5f7 | 608 | }); |
af3838c5 | 609 | return days.join(', '); |
2bdf9dd3 | 610 | } |
ad74d86c DM |
611 | }, |
612 | { | |
613 | header: gettext('Start Time'), | |
614 | width: 60, | |
615 | sortable: true, | |
616 | dataIndex: 'starttime' | |
617 | }, | |
618 | { | |
619 | header: gettext('Storage'), | |
620 | width: 100, | |
621 | sortable: true, | |
622 | dataIndex: 'storage' | |
623 | }, | |
624 | { | |
625 | header: gettext('Selection'), | |
626 | flex: 1, | |
627 | sortable: false, | |
628 | dataIndex: 'vmid', | |
629 | renderer: function(value, metaData, record) { | |
630 | /*jslint confusion: true */ | |
631 | if (record.data.all) { | |
632 | if (record.data.exclude) { | |
633 | return Ext.String.format(me.allExceptText, record.data.exclude); | |
634 | } | |
635 | return me.allText; | |
636 | } | |
637 | if (record.data.vmid) { | |
638 | return record.data.vmid; | |
639 | } | |
640 | ||
ab648869 | 641 | if (record.data.pool) { |
a82afef0 | 642 | return "Pool '"+ record.data.pool + "'"; |
ab648869 TM |
643 | } |
644 | ||
ad74d86c DM |
645 | return "-"; |
646 | } | |
647 | } | |
648 | ], | |
649 | listeners: { | |
c0b3df6e | 650 | activate: reload, |
ad74d86c DM |
651 | itemdblclick: run_editor |
652 | } | |
653 | }); | |
60e049c2 | 654 | |
ad74d86c DM |
655 | me.callParent(); |
656 | } | |
657 | }, function() { | |
658 | ||
659 | Ext.define('pve-cluster-backup', { | |
660 | extend: 'Ext.data.Model', | |
60e049c2 | 661 | fields: [ |
ad74d86c DM |
662 | 'id', 'starttime', 'dow', |
663 | 'storage', 'node', 'vmid', 'exclude', | |
389d3cf1 | 664 | 'mailto', 'pool', 'compress', 'mode', |
cfdc7ada | 665 | { name: 'enabled', type: 'boolean' }, |
389d3cf1 | 666 | { name: 'all', type: 'boolean' } |
ad74d86c DM |
667 | ] |
668 | }); | |
cfdc7ada | 669 | }); |