]>
Commit | Line | Data |
---|---|---|
7bd89462 DM |
1 | Ext.define('PVE.grid.BackupView', { |
2 | extend: 'Ext.grid.GridPanel', | |
3 | ||
4 | alias: ['widget.pveBackupView'], | |
5 | ||
ba93a9c6 | 6 | onlineHelp: 'chapter_vzdump', |
7bd89462 | 7 | |
a61607a8 DC |
8 | stateful: true, |
9 | stateId: 'grid-guest-backup', | |
10 | ||
8058410f | 11 | initComponent: function() { |
7bd89462 DM |
12 | var me = this; |
13 | ||
14 | var nodename = me.pveSelNode.data.node; | |
15 | if (!nodename) { | |
16 | throw "no node name specified"; | |
17 | } | |
18 | ||
19 | var vmid = me.pveSelNode.data.vmid; | |
20 | if (!vmid) { | |
21 | throw "no VM ID specified"; | |
22 | } | |
23 | ||
24 | var vmtype = me.pveSelNode.data.type; | |
25 | if (!vmtype) { | |
26 | throw "no VM type specified"; | |
27 | } | |
28 | ||
2685b382 | 29 | var vmtypeFilter; |
3b8f599b | 30 | if (vmtype === 'lxc' || vmtype === 'openvz') { |
2685b382 | 31 | vmtypeFilter = function(item) { |
3b8f599b | 32 | return PVE.Utils.volume_is_lxc_backup(item.data.volid, item.data.format); |
7bd89462 DM |
33 | }; |
34 | } else if (vmtype === 'qemu') { | |
2685b382 | 35 | vmtypeFilter = function(item) { |
3b8f599b | 36 | return PVE.Utils.volume_is_qemu_backup(item.data.volid, item.data.format); |
7bd89462 DM |
37 | }; |
38 | } else { | |
39 | throw "unsupported VM type '" + vmtype + "'"; | |
40 | } | |
41 | ||
ce76a18a EK |
42 | var searchFilter = { |
43 | property: 'volid', | |
201b89db | 44 | value: '', |
ce76a18a | 45 | anyMatch: true, |
f6710aac | 46 | caseSensitive: false, |
ce76a18a EK |
47 | }; |
48 | ||
201b89db DC |
49 | var vmidFilter = { |
50 | property: 'vmid', | |
51 | value: vmid, | |
496eb1cc | 52 | exactMatch: true, |
201b89db DC |
53 | }; |
54 | ||
7bd89462 DM |
55 | me.store = Ext.create('Ext.data.Store', { |
56 | model: 'pve-storage-content', | |
2a4971d8 TL |
57 | sorters: { |
58 | property: 'volid', | |
f6710aac | 59 | order: 'DESC', |
7bd89462 | 60 | }, |
ce76a18a | 61 | filters: [ |
2685b382 | 62 | vmtypeFilter, |
201b89db DC |
63 | searchFilter, |
64 | vmidFilter, | |
f6710aac | 65 | ], |
7bd89462 DM |
66 | }); |
67 | ||
201b89db DC |
68 | let updateFilter = function() { |
69 | me.store.filter([ | |
70 | vmtypeFilter, | |
71 | searchFilter, | |
72 | vmidFilter, | |
73 | ]); | |
74 | }; | |
75 | ||
7bd89462 | 76 | var reload = Ext.Function.createBuffered(function() { |
8dfd00cd | 77 | if (me.store) { |
7bd89462 DM |
78 | me.store.load(); |
79 | } | |
80 | }, 100); | |
81 | ||
82 | var setStorage = function(storage) { | |
83 | var url = '/api2/json/nodes/' + nodename + '/storage/' + storage + '/content'; | |
84 | url += '?content=backup'; | |
85 | ||
86 | me.store.setProxy({ | |
56a353b9 | 87 | type: 'proxmox', |
f6710aac | 88 | url: url, |
7bd89462 DM |
89 | }); |
90 | ||
91 | reload(); | |
92 | }; | |
93 | ||
94 | var storagesel = Ext.create('PVE.form.StorageSelector', { | |
95 | nodename: nodename, | |
96 | fieldLabel: gettext('Storage'), | |
97 | labelAlign: 'right', | |
98 | storageContent: 'backup', | |
99 | allowBlank: false, | |
100 | listeners: { | |
101 | change: function(f, value) { | |
8267aa63 | 102 | let storage = f.getStore().findRecord('storage', value, 0, false, true, true); |
957a53bd | 103 | if (storage) { |
814c5942 | 104 | let isPBS = storage.data.type === 'pbs'; |
957a53bd | 105 | me.getColumns().forEach((column) => { |
3003a59d TL |
106 | let id = column.dataIndex; |
107 | if (id === 'verification' || id === 'encrypted') { | |
814c5942 | 108 | column.setHidden(!isPBS); |
957a53bd DC |
109 | } |
110 | }); | |
111 | } | |
7bd89462 | 112 | setStorage(value); |
f6710aac TL |
113 | }, |
114 | }, | |
7bd89462 DM |
115 | }); |
116 | ||
117 | var storagefilter = Ext.create('Ext.form.field.Text', { | |
118 | fieldLabel: gettext('Search'), | |
119 | labelWidth: 50, | |
120 | labelAlign: 'right', | |
121 | enableKeyEvents: true, | |
ce76a18a | 122 | value: searchFilter.value, |
7bd89462 DM |
123 | listeners: { |
124 | buffer: 500, | |
125 | keyup: function(field) { | |
126 | me.store.clearFilter(true); | |
ce76a18a | 127 | searchFilter.value = field.getValue(); |
201b89db | 128 | updateFilter(); |
f6710aac TL |
129 | }, |
130 | }, | |
7bd89462 DM |
131 | }); |
132 | ||
201b89db | 133 | var vmidfilterCB = Ext.create('Ext.form.field.Checkbox', { |
a7c90b40 | 134 | boxLabel: gettext('Filter VMID'), |
201b89db DC |
135 | value: '1', |
136 | listeners: { | |
137 | change: function(cb, value) { | |
814c5942 | 138 | vmidFilter.value = value ? vmid : ''; |
ac27dd32 | 139 | vmidFilter.exactMatch = !!value; |
201b89db DC |
140 | updateFilter(); |
141 | }, | |
142 | }, | |
143 | }); | |
144 | ||
7bd89462 DM |
145 | var sm = Ext.create('Ext.selection.RowModel', {}); |
146 | ||
147 | var backup_btn = Ext.create('Ext.button.Button', { | |
148 | text: gettext('Backup now'), | |
149 | handler: function() { | |
2a4971d8 | 150 | var win = Ext.create('PVE.window.Backup', { |
7bd89462 DM |
151 | nodename: nodename, |
152 | vmid: vmid, | |
153 | vmtype: vmtype, | |
e83e60bf | 154 | storage: storagesel.getValue(), |
8058410f | 155 | listeners: { |
e83e60bf EK |
156 | close: function() { |
157 | reload(); | |
f6710aac TL |
158 | }, |
159 | }, | |
7bd89462 DM |
160 | }); |
161 | win.show(); | |
f6710aac | 162 | }, |
7bd89462 DM |
163 | }); |
164 | ||
5720fafa | 165 | var restore_btn = Ext.create('Proxmox.button.Button', { |
7bd89462 DM |
166 | text: gettext('Restore'), |
167 | disabled: true, | |
168 | selModel: sm, | |
169 | enableFn: function(rec) { | |
170 | return !!rec; | |
171 | }, | |
172 | handler: function(b, e, rec) { | |
814c5942 | 173 | let win = Ext.create('PVE.window.Restore', { |
7bd89462 DM |
174 | nodename: nodename, |
175 | vmid: vmid, | |
176 | volid: rec.data.volid, | |
177 | volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec), | |
f6710aac | 178 | vmtype: vmtype, |
7bd89462 DM |
179 | }); |
180 | win.show(); | |
181 | win.on('destroy', reload); | |
f6710aac | 182 | }, |
7bd89462 DM |
183 | }); |
184 | ||
3b1ca3ff | 185 | var delete_btn = Ext.create('Proxmox.button.StdRemoveButton', { |
7bd89462 | 186 | selModel: sm, |
3b1ca3ff | 187 | dangerous: true, |
4d23cdef | 188 | delay: 5, |
7bd89462 DM |
189 | confirmMsg: function(rec) { |
190 | var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'), | |
191 | "'" + rec.data.volid + "'"); | |
16152937 | 192 | msg += " " + gettext('This will permanently erase all data.'); |
7bd89462 DM |
193 | |
194 | return msg; | |
195 | }, | |
3b1ca3ff | 196 | getUrl: function(rec) { |
7bd89462 | 197 | var storage = storagesel.getValue(); |
3b1ca3ff DC |
198 | return '/nodes/' + nodename + '/storage/' + storage + '/content/' + rec.data.volid; |
199 | }, | |
200 | callback: function() { | |
201 | reload(); | |
f6710aac | 202 | }, |
7bd89462 DM |
203 | }); |
204 | ||
5720fafa | 205 | var config_btn = Ext.create('Proxmox.button.Button', { |
79f305de DC |
206 | text: gettext('Show Configuration'), |
207 | disabled: true, | |
208 | selModel: sm, | |
209 | enableFn: function(rec) { | |
210 | return !!rec; | |
211 | }, | |
212 | handler: function(b, e, rec) { | |
213 | var storage = storagesel.getValue(); | |
214 | if (!storage) { | |
215 | return; | |
216 | } | |
217 | ||
6da4aea8 DC |
218 | var win = Ext.create('PVE.window.BackupConfig', { |
219 | volume: rec.data.volid, | |
f6710aac | 220 | pveSelNode: me.pveSelNode, |
79f305de DC |
221 | }); |
222 | ||
6da4aea8 | 223 | win.show(); |
f6710aac | 224 | }, |
79f305de DC |
225 | }); |
226 | ||
7bd89462 | 227 | Ext.apply(me, { |
7bd89462 | 228 | selModel: sm, |
201b89db DC |
229 | tbar: { |
230 | overflowHandler: 'scroller', | |
a6d960f1 DC |
231 | items: [ |
232 | backup_btn, | |
233 | restore_btn, | |
234 | delete_btn, | |
fbbb2a14 | 235 | '-', |
a6d960f1 | 236 | config_btn, |
fbbb2a14 | 237 | '-', |
a6d960f1 DC |
238 | { |
239 | xtype: 'proxmoxButton', | |
240 | text: gettext('Edit Notes'), | |
241 | disabled: true, | |
242 | enableFn: function() { | |
243 | let storageVal = storagesel.getValue(); | |
8267aa63 DC |
244 | let storage = storagesel |
245 | .getStore() | |
246 | .findRecord('storage', storageVal, 0, false, true, true); | |
a6d960f1 DC |
247 | if (storage) { |
248 | return storage.data.type !== 'pbs'; | |
249 | } | |
250 | return true; | |
251 | }, | |
252 | handler: function() { | |
253 | let volid = sm.getSelection()[0].data.volid; | |
254 | var storage = storagesel.getValue(); | |
255 | Ext.create('Proxmox.window.Edit', { | |
256 | autoLoad: true, | |
257 | width: 600, | |
258 | height: 400, | |
259 | resizable: true, | |
fbbb2a14 | 260 | title: gettext('Notes'), |
a6d960f1 DC |
261 | url: `/api2/extjs/nodes/${nodename}/storage/${storage}/content/${volid}`, |
262 | layout: 'fit', | |
263 | items: [ | |
264 | { | |
265 | xtype: 'textarea', | |
266 | layout: 'fit', | |
267 | name: 'notes', | |
268 | height: '100%', | |
269 | }, | |
270 | ], | |
271 | listeners: { | |
fbbb2a14 | 272 | destroy: () => reload(), |
a6d960f1 DC |
273 | }, |
274 | }).show(); | |
275 | }, | |
276 | }, | |
277 | '->', | |
278 | storagesel, | |
279 | '-', | |
280 | vmidfilterCB, | |
f6710aac | 281 | storagefilter, |
a6d960f1 | 282 | ], |
201b89db | 283 | }, |
7bd89462 DM |
284 | columns: [ |
285 | { | |
286 | header: gettext('Name'), | |
425e05d7 | 287 | flex: 2, |
7bd89462 DM |
288 | sortable: true, |
289 | renderer: PVE.Utils.render_storage_content, | |
f6710aac | 290 | dataIndex: 'volid', |
7bd89462 | 291 | }, |
425e05d7 | 292 | { |
ef402242 DC |
293 | header: gettext('Notes'), |
294 | dataIndex: 'notes', | |
425e05d7 TL |
295 | flex: 1, |
296 | renderer: Ext.htmlEncode, | |
297 | }, | |
afd3b071 TL |
298 | { |
299 | header: gettext('Date'), | |
300 | width: 150, | |
f6710aac | 301 | dataIndex: 'vdate', |
afd3b071 | 302 | }, |
7bd89462 DM |
303 | { |
304 | header: gettext('Format'), | |
305 | width: 100, | |
f6710aac | 306 | dataIndex: 'format', |
7bd89462 DM |
307 | }, |
308 | { | |
309 | header: gettext('Size'), | |
310 | width: 100, | |
e7ade592 | 311 | renderer: Proxmox.Utils.format_size, |
f6710aac | 312 | dataIndex: 'size', |
201b89db DC |
313 | }, |
314 | { | |
315 | header: gettext('VMID'), | |
316 | dataIndex: 'vmid', | |
317 | hidden: true, | |
318 | }, | |
3003a59d TL |
319 | { |
320 | header: gettext('Encrypted'), | |
321 | dataIndex: 'encrypted', | |
322 | renderer: PVE.Utils.render_backup_encryption, | |
323 | }, | |
957a53bd DC |
324 | { |
325 | header: gettext('Verify State'), | |
326 | dataIndex: 'verification', | |
770d614f | 327 | renderer: PVE.Utils.render_backup_verification, |
f6710aac TL |
328 | }, |
329 | ], | |
7bd89462 DM |
330 | }); |
331 | ||
332 | me.callParent(); | |
f6710aac | 333 | }, |
7bd89462 | 334 | }); |