]>
Commit | Line | Data |
---|---|---|
8f795124 DC |
1 | /*global |
2 | FileReader | |
3 | */ | |
256a65a4 | 4 | |
09358a73 DM |
5 | Ext.define('PVE.lxc.CreateWizard', { |
6 | extend: 'PVE.window.Wizard', | |
7 | ||
b1339314 WB |
8 | loadSSHKeyFromFile: function(file) { |
9 | var me = this; | |
10 | // ssh-keygen produces 740 bytes for an average 4096 bit rsa key, with | |
11 | // a user@host comment, 1420 for 8192 bits; current max is 16kbit | |
12 | // assume: 740*8 for max. 32kbit (5920 byte file) | |
13 | // round upwards to nearest nice number => 8192 bytes, leaves lots of comment space | |
14 | if (file.size > 8192) { | |
15 | Ext.Msg.alert(gettext('Error'), gettext("Invalid file size: ") + file.size); | |
16 | return; | |
17 | } | |
18 | var reader = new FileReader(); | |
19 | reader.onload = function(evt) { | |
20 | me.sshkeyfield.setValue(evt.target.result); | |
21 | }; | |
22 | reader.readAsText(file); | |
23 | }, | |
24 | ||
09358a73 DM |
25 | initComponent: function() { |
26 | var me = this; | |
27 | ||
28 | var summarystore = Ext.create('Ext.data.Store', { | |
29 | model: 'KeyValue', | |
30 | sorters: [ | |
31 | { | |
32 | property : 'key', | |
33 | direction: 'ASC' | |
34 | } | |
35 | ] | |
36 | }); | |
37 | ||
38 | var tmplsel = Ext.create('PVE.form.FileSelector', { | |
39 | name: 'ostemplate', | |
40 | storageContent: 'vztmpl', | |
41 | fieldLabel: gettext('Template'), | |
42 | allowBlank: false | |
43 | }); | |
44 | ||
45 | var tmplstoragesel = Ext.create('PVE.form.StorageSelector', { | |
46 | name: 'tmplstorage', | |
47 | fieldLabel: gettext('Storage'), | |
48 | storageContent: 'vztmpl', | |
49 | autoSelect: true, | |
50 | allowBlank: false, | |
51 | listeners: { | |
52 | change: function(f, value) { | |
53 | tmplsel.setStorage(value); | |
54 | } | |
55 | } | |
56 | }); | |
57 | ||
58 | var rootfspanel = Ext.create('PVE.lxc.MountPointInputPanel', { | |
59 | title: gettext('Root Disk'), | |
60 | insideWizard: true, | |
d5e771ce | 61 | isCreate: true, |
09358a73 | 62 | unused: false, |
c15e9cd5 | 63 | unprivileged: false, |
09358a73 DM |
64 | confid: 'rootfs' |
65 | }); | |
66 | ||
67 | var networkpanel = Ext.create('PVE.lxc.NetworkInputPanel', { | |
68 | title: gettext('Network'), | |
69 | insideWizard: true, | |
70 | dataCache: {}, | |
d5e771ce | 71 | isCreate: true |
09358a73 DM |
72 | }); |
73 | ||
b1339314 WB |
74 | var passwordfield = Ext.createWidget('textfield', { |
75 | inputType: 'password', | |
76 | name: 'password', | |
77 | value: '', | |
78 | fieldLabel: gettext('Password'), | |
79 | allowBlank: false, | |
80 | minLength: 5, | |
81 | change: function(f, value) { | |
82 | if (!me.rendered) { | |
83 | return; | |
84 | } | |
85 | me.down('field[name=confirmpw]').validate(); | |
86 | } | |
87 | }); | |
88 | ||
256a65a4 EK |
89 | /*jslint confusion: true */ |
90 | /* the validator function can return either a string or a boolean */ | |
dbed4c1c | 91 | me.sshkeyfield = Ext.createWidget('proxmoxtextfield', { |
b1339314 WB |
92 | name: 'ssh-public-keys', |
93 | value: '', | |
94 | fieldLabel: gettext('SSH public key'), | |
95 | allowBlank: true, | |
96 | validator: function(value) { | |
97 | if (value.length) { | |
98 | var key = PVE.Parser.parseSSHKey(value); | |
99 | if (!key) { | |
100 | return "Failed to recognize ssh key"; | |
101 | } | |
102 | me.down('field[name=password]').allowBlank = true; | |
103 | } else { | |
104 | me.down('field[name=password]').allowBlank = false; | |
105 | } | |
106 | me.down('field[name=password]').validate(); | |
107 | return true; | |
108 | }, | |
109 | afterRender: function() { | |
110 | if (!window.FileReader) { | |
111 | // No FileReader support in this browser | |
112 | return; | |
113 | } | |
114 | var cancel = function(ev) { | |
115 | ev = ev.event; | |
116 | if (ev.preventDefault) { | |
117 | ev.preventDefault(); | |
118 | } | |
119 | }; | |
120 | me.sshkeyfield.inputEl.on('dragover', cancel); | |
121 | me.sshkeyfield.inputEl.on('dragenter', cancel); | |
122 | me.sshkeyfield.inputEl.on('drop', function(ev) { | |
123 | ev = ev.event; | |
124 | if (ev.preventDefault) { | |
125 | ev.preventDefault(); | |
126 | } | |
127 | var files = ev.dataTransfer.files; | |
128 | me.loadSSHKeyFromFile(files[0]); | |
129 | }); | |
8f795124 | 130 | } |
b1339314 WB |
131 | }); |
132 | ||
133 | var column2 = [ | |
134 | { | |
135 | xtype: 'pvePoolSelector', | |
136 | fieldLabel: gettext('Resource Pool'), | |
137 | name: 'pool', | |
138 | value: '', | |
139 | allowBlank: true | |
140 | }, | |
141 | passwordfield, | |
142 | { | |
143 | xtype: 'textfield', | |
144 | inputType: 'password', | |
145 | name: 'confirmpw', | |
146 | value: '', | |
147 | fieldLabel: gettext('Confirm password'), | |
148 | allowBlank: true, | |
149 | validator: function(value) { | |
150 | var pw = me.down('field[name=password]').getValue(); | |
151 | if (pw !== value) { | |
fd776fca | 152 | return "Passwords do not match!"; |
b1339314 WB |
153 | } |
154 | return true; | |
155 | } | |
156 | }, | |
157 | me.sshkeyfield | |
158 | ]; | |
256a65a4 | 159 | /*jslint confusion: false */ |
b1339314 WB |
160 | |
161 | if (window.FileReader) { | |
162 | column2.push({ | |
163 | xtype: 'filebutton', | |
164 | name: 'file', | |
165 | text: gettext('Load SSH Key File'), | |
166 | listeners: { | |
167 | change: function(btn, e, value) { | |
168 | e = e.event; | |
169 | me.loadSSHKeyFromFile(e.target.files[0]); | |
170 | btn.reset(); | |
171 | } | |
172 | } | |
173 | }); | |
174 | } | |
175 | ||
09358a73 DM |
176 | Ext.applyIf(me, { |
177 | subject: gettext('LXC Container'), | |
178 | items: [ | |
179 | { | |
180 | xtype: 'inputpanel', | |
181 | title: gettext('General'), | |
ff05aec0 | 182 | onlineHelp: 'pct_general', |
09358a73 DM |
183 | column1: [ |
184 | { | |
2d0aa6d1 | 185 | xtype: 'pveNodeSelector', |
09358a73 | 186 | name: 'nodename', |
05c4b764 DC |
187 | selectCurNode: !me.nodename, |
188 | preferredValue: me.nodename, | |
09358a73 DM |
189 | fieldLabel: gettext('Node'), |
190 | allowBlank: false, | |
191 | onlineValidator: true, | |
192 | listeners: { | |
193 | change: function(f, value) { | |
194 | tmplstoragesel.setNodename(value); | |
195 | tmplsel.setStorage(undefined, value); | |
196 | networkpanel.setNodename(value); | |
197 | rootfspanel.setNodename(value); | |
198 | } | |
199 | } | |
200 | }, | |
201 | { | |
ed416f20 EK |
202 | xtype: 'pveGuestIDSelector', |
203 | name: 'vmid', // backend only knows vmid | |
204 | guestType: 'lxc', | |
09358a73 | 205 | value: '', |
ed416f20 | 206 | loadNextFreeID: true, |
09358a73 DM |
207 | validateExists: false |
208 | }, | |
209 | { | |
dbed4c1c | 210 | xtype: 'proxmoxtextfield', |
09358a73 DM |
211 | name: 'hostname', |
212 | vtype: 'DnsName', | |
213 | value: '', | |
214 | fieldLabel: gettext('Hostname'), | |
215 | skipEmptyText: true, | |
216 | allowBlank: true | |
a97bc800 EK |
217 | }, |
218 | { | |
219 | xtype: 'pvecheckbox', | |
220 | name: 'unprivileged', | |
221 | value: '', | |
c15e9cd5 PA |
222 | listeners: { |
223 | change: function(f, value) { | |
224 | if (value) { | |
225 | rootfspanel.down('field[name=quota]').setValue(false); | |
226 | } | |
227 | rootfspanel.unprivileged = value; | |
234d2e37 | 228 | var hdsel = rootfspanel.down('#hdstorage'); |
c15e9cd5 PA |
229 | hdsel.fireEvent('change', hdsel, hdsel.getValue()); |
230 | } | |
231 | }, | |
a97bc800 | 232 | fieldLabel: gettext('Unprivileged container') |
09358a73 DM |
233 | } |
234 | ], | |
b1339314 | 235 | column2: column2, |
09358a73 DM |
236 | onGetValues: function(values) { |
237 | delete values.confirmpw; | |
238 | if (!values.pool) { | |
239 | delete values.pool; | |
240 | } | |
241 | return values; | |
242 | } | |
243 | }, | |
244 | { | |
245 | xtype: 'inputpanel', | |
246 | title: gettext('Template'), | |
c8802a60 | 247 | onlineHelp: 'pct_container_images', |
09358a73 DM |
248 | column1: [ tmplstoragesel, tmplsel] |
249 | }, | |
250 | rootfspanel, | |
251 | { | |
252 | xtype: 'pveLxcCPUInputPanel', | |
253 | title: gettext('CPU'), | |
254 | insideWizard: true | |
255 | }, | |
256 | { | |
257 | xtype: 'pveLxcMemoryInputPanel', | |
258 | title: gettext('Memory'), | |
259 | insideWizard: true | |
260 | }, | |
261 | networkpanel, | |
262 | { | |
263 | xtype: 'pveLxcDNSInputPanel', | |
264 | title: gettext('DNS'), | |
265 | insideWizard: true | |
266 | }, | |
267 | { | |
268 | title: gettext('Confirm'), | |
269 | layout: 'fit', | |
270 | items: [ | |
271 | { | |
09358a73 DM |
272 | xtype: 'grid', |
273 | store: summarystore, | |
274 | columns: [ | |
275 | {header: 'Key', width: 150, dataIndex: 'key'}, | |
276 | {header: 'Value', flex: 1, dataIndex: 'value'} | |
277 | ] | |
278 | } | |
279 | ], | |
280 | listeners: { | |
281 | show: function(panel) { | |
282 | var form = me.down('form').getForm(); | |
283 | var kv = me.getValues(); | |
284 | var data = []; | |
285 | Ext.Object.each(kv, function(key, value) { | |
286 | if (key === 'delete' || key === 'tmplstorage') { // ignore | |
287 | return; | |
288 | } | |
289 | if (key === 'password') { // don't show pw | |
290 | return; | |
291 | } | |
292 | var html = Ext.htmlEncode(Ext.JSON.encode(value)); | |
293 | data.push({ key: key, value: value }); | |
294 | }); | |
295 | summarystore.suspendEvents(); | |
296 | summarystore.removeAll(); | |
297 | summarystore.add(data); | |
298 | summarystore.sort(); | |
299 | summarystore.resumeEvents(); | |
59f2dd3d | 300 | summarystore.fireEvent('refresh'); |
09358a73 DM |
301 | } |
302 | }, | |
303 | onSubmit: function() { | |
304 | var kv = me.getValues(); | |
305 | delete kv['delete']; | |
306 | ||
307 | var nodename = kv.nodename; | |
308 | delete kv.nodename; | |
309 | delete kv.tmplstorage; | |
310 | ||
83576841 | 311 | if (!kv.password.length && kv['ssh-public-keys']) { |
8f795124 | 312 | delete kv.password; |
b1339314 WB |
313 | } |
314 | ||
e7ade592 | 315 | Proxmox.Utils.API2Request({ |
09358a73 DM |
316 | url: '/nodes/' + nodename + '/lxc', |
317 | waitMsgTarget: me, | |
318 | method: 'POST', | |
319 | params: kv, | |
320 | success: function(response, opts){ | |
321 | var upid = response.result.data; | |
fd776fca PA |
322 | |
323 | var win = Ext.create('PVE.window.TaskViewer', { | |
09358a73 DM |
324 | upid: upid |
325 | }); | |
326 | win.show(); | |
327 | me.close(); | |
328 | }, | |
329 | failure: function(response, opts) { | |
330 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
331 | } | |
332 | }); | |
333 | } | |
334 | } | |
335 | ] | |
336 | }); | |
337 | ||
338 | me.callParent(); | |
339 | } | |
340 | }); | |
341 | ||
342 | ||
343 |