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