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