]>
Commit | Line | Data |
---|---|---|
d7683c68 | 1 | Ext.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 | }); |