]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/window/Restore.js
ui: backup restore: rework to leverage more viewcontroller and cleanup
[pve-manager.git] / www / manager6 / window / Restore.js
CommitLineData
d7683c68 1Ext.define('PVE.window.Restore', {
9fccc702 2 extend: 'Ext.window.Window', // fixme: Proxmox.window.Edit?
d7683c68
DM
3
4 resizable: false,
d3de9b55
TL
5 width: 500,
6 modal: true,
7 layout: 'auto',
8 border: false,
d7683c68 9
878bbf0b
SR
10 controller: {
11 xclass: 'Ext.app.ViewController',
12 control: {
13 '#liveRestore': {
14 change: function(el, newVal) {
15 let liveWarning = this.lookupReference('liveWarning');
16 liveWarning.setHidden(!newVal);
17 let start = this.lookupReference('start');
18 start.setDisabled(newVal);
19 },
20 },
d3de9b55
TL
21 'form': {
22 validitychange: function(f, valid) {
23 this.lookupReference('doRestoreBtn').setDisabled(!valid);
24 },
25 },
26 },
27
28 doRestore: function() {
29 let me = this;
30 let view = me.getView();
31
32 let values = view.down('form').getForm().getValues();
33
34 let params = {
35 vmid: view.vmid || values.vmid,
36 force: view.vmid ? 1 : 0,
37 };
38 if (values.unique) {
39 params.unique = 1;
40 }
41 if (values.start && !values['live-restore']) {
42 params.start = 1;
43 }
44 if (values['live-restore']) {
45 params['live-restore'] = 1;
46 }
47 if (values.storage) {
48 params.storage = values.storage;
49 }
50 if (values.bwlimit !== undefined) {
51 params.bwlimit = values.bwlimit;
52 }
53
54 let confirmMsg;
55 if (view.vmtype === 'lxc') {
56 params.ostemplate = view.volid;
57 params.restore = 1;
58 if (values.unprivileged !== 'keep') {
59 params.unprivileged = values.unprivileged;
60 }
61 confirmMsg = Proxmox.Utils.format_task_description('vzrestore', params.vmid);
62 } else if (view.vmtype === 'qemu') {
63 params.archive = view.volid;
64 confirmMsg = Proxmox.Utils.format_task_description('qmrestore', params.vmid);
65 } else {
66 throw 'unknown VM type';
67 }
68
69 let executeRestore = () => {
70 Proxmox.Utils.API2Request({
71 url: `/nodes/${view.nodename}/${view.vmtype}`,
72 params: params,
73 method: 'POST',
74 waitMsgTarget: view,
75 failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
76 success: function(response, options) {
77 Ext.create('Proxmox.window.TaskViewer', {
78 autoShow: true,
79 upid: response.result.data,
80 });
81 view.close();
82 },
83 });
84 };
85
86 if (view.vmid) {
87 confirmMsg += '. ' + gettext('This will permanently erase current VM data.');
88 Ext.Msg.confirm(gettext('Confirm'), confirmMsg, function(btn) {
89 if (btn === 'yes') {
90 executeRestore();
91 }
92 });
93 } else {
94 executeRestore();
95 }
878bbf0b
SR
96 },
97 },
98
8058410f 99 initComponent: function() {
d3de9b55 100 let me = this;
d7683c68
DM
101
102 if (!me.nodename) {
103 throw "no node name specified";
104 }
d7683c68
DM
105 if (!me.volid) {
106 throw "no volume ID specified";
107 }
d7683c68
DM
108 if (!me.vmtype) {
109 throw "no vmtype specified";
110 }
111
d3de9b55 112 let storagesel = Ext.create('PVE.form.StorageSelector', {
d7683c68
DM
113 nodename: me.nodename,
114 name: 'storage',
115 value: '',
116 fieldLabel: gettext('Storage'),
53e3ea84 117 storageContent: me.vmtype === 'lxc' ? 'rootdir' : 'images',
6fe863ba
FE
118 // when restoring a container without specifying a storage, the backend defaults
119 // to 'local', which is unintuitive and 'rootdir' might not even be allowed on it
120 allowBlank: me.vmtype !== 'lxc',
53e3ea84 121 emptyText: me.vmtype === 'lxc' ? '' : gettext('From backup configuration'),
6fe863ba 122 autoSelect: me.vmtype === 'lxc',
d7683c68
DM
123 });
124
d3de9b55 125 let IDfield;
ed416f20
EK
126 if (me.vmid) {
127 IDfield = Ext.create('Ext.form.field.Display', {
128 name: 'vmid',
129 value: me.vmid,
53e3ea84 130 fieldLabel: me.vmtype === 'lxc' ? 'CT' : 'VM',
ed416f20
EK
131 });
132 } else {
133 IDfield = Ext.create('PVE.form.GuestIDSelector', {
134 name: 'vmid',
135 guestType: me.vmtype,
677bb0e8 136 loadNextFreeID: true,
f6710aac 137 validateExists: false,
ed416f20
EK
138 });
139 }
140
d3de9b55 141 let items = [
9cf2e84b
DM
142 {
143 xtype: 'displayfield',
144 value: me.volidText || me.volid,
f6710aac 145 fieldLabel: gettext('Source'),
9cf2e84b
DM
146 },
147 storagesel,
9fa4ce6d
TL
148 IDfield,
149 {
a331258a 150 xtype: 'pveBandwidthField',
9fa4ce6d 151 name: 'bwlimit',
0545b2a5 152 backendUnit: 'KiB',
9ae4a024
FE
153 allowZero: true,
154 fieldLabel: gettext('Bandwidth Limit'),
9fa4ce6d
TL
155 emptyText: gettext('Defaults to target storage restore limit'),
156 autoEl: {
157 tag: 'div',
f6710aac
TL
158 'data-qtip': gettext("Use '0' to disable all bandwidth limits."),
159 },
c517e212 160 },
8b030d08 161 {
24c55f41
TL
162 xtype: 'fieldcontainer',
163 layout: 'hbox',
164 items: [{
165 xtype: 'proxmoxcheckbox',
166 name: 'unique',
167 fieldLabel: gettext('Unique'),
168 hidden: !!me.vmid,
169 flex: 1,
170 autoEl: {
171 tag: 'div',
f6710aac 172 'data-qtip': gettext('Autogenerate unique properties, e.g., MAC addresses'),
24c55f41 173 },
f6710aac 174 checked: false,
8b030d08 175 },
24c55f41
TL
176 {
177 xtype: 'proxmoxcheckbox',
178 name: 'start',
878bbf0b 179 reference: 'start',
24c55f41
TL
180 flex: 1,
181 fieldLabel: gettext('Start after restore'),
182 labelWidth: 105,
f6710aac 183 checked: false,
24c55f41
TL
184 }],
185 },
9cf2e84b
DM
186 ];
187
188 if (me.vmtype === 'lxc') {
6da2926c
TL
189 items.push(
190 {
191 xtype: 'radiogroup',
192 fieldLabel: gettext('Privilege Level'),
193 reference: 'noVNCScalingGroup',
194 height: '15px', // renders faster with value assigned
195 layout: {
196 type: 'hbox',
197 algin: 'stretch',
198 },
199 autoEl: {
200 tag: 'div',
201 'data-qtip':
202 gettext('Choose if you want to keep or override the privilege level of the restored Container.'),
203 },
204 items: [
205 {
206 xtype: 'radiofield',
207 name: 'unprivileged',
208 inputValue: 'keep',
209 boxLabel: gettext('From Backup'),
210 flex: 1,
211 checked: true,
212 },
213 {
214 xtype: 'radiofield',
215 name: 'unprivileged',
216 inputValue: '1',
217 boxLabel: gettext('Unprivileged'),
218 flex: 1,
219 },
220 {
221 xtype: 'radiofield',
222 name: 'unprivileged',
223 inputValue: '0',
224 boxLabel: gettext('Privileged'),
225 flex: 1,
226 //margin: '0 0 0 10',
227 },
228 ],
229 },
230 );
878bbf0b
SR
231 } else if (me.vmtype === 'qemu') {
232 items.push({
233 xtype: 'proxmoxcheckbox',
234 name: 'live-restore',
235 itemId: 'liveRestore',
236 flex: 1,
237 fieldLabel: gettext('Live restore'),
238 checked: false,
239 hidden: !me.isPBS,
240 // align checkbox with 'start' if 'unique' is hidden
241 labelWidth: me.vmid ? 105 : 100,
d3de9b55
TL
242 },
243 {
878bbf0b
SR
244 xtype: 'displayfield',
245 reference: 'liveWarning',
246 // TODO: Remove once more tested/stable?
d290acc8 247 value: gettext('Note: If anything goes wrong during the live-restore, new data written by the VM may be lost.'),
878bbf0b
SR
248 userCls: 'pmx-hint',
249 hidden: true,
250 });
9cf2e84b
DM
251 }
252
d3de9b55 253 let title = gettext('Restore') + ": " + (me.vmtype === 'lxc' ? 'CT' : 'VM');
185a77e5
DM
254 if (me.vmid) {
255 title += " " + me.vmid;
256 }
d7683c68
DM
257
258 Ext.apply(me, {
259 title: title,
d3de9b55
TL
260 items: [
261 {
262 xtype: 'form',
263 bodyPadding: 10,
264 border: false,
265 fieldDefaults: {
266 labelWidth: 100,
267 anchor: '100%',
268 },
269 items: items,
270 },
271 ],
272 buttons: [
273 {
274 text: gettext('Restore'),
275 reference: 'doRestoreBtn',
276 handler: 'doRestore',
277 },
278 ],
d7683c68
DM
279 });
280
281 me.callParent();
f6710aac 282 },
d7683c68 283});