]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/CreateWizard.js
Add the possibility to create an unprivileged container at creation time in the GUI.
[pve-manager.git] / www / manager6 / lxc / CreateWizard.js
1 /*global
2 FileReader
3 */
4 /*jslint confusion: true */
5 Ext.define('PVE.lxc.CreateWizard', {
6 extend: 'PVE.window.Wizard',
7
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
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,
61 create: true,
62 unused: false,
63 confid: 'rootfs'
64 });
65
66 var networkpanel = Ext.create('PVE.lxc.NetworkInputPanel', {
67 title: gettext('Network'),
68 insideWizard: true,
69 dataCache: {},
70 create: true
71 });
72
73 var passwordfield = Ext.createWidget('textfield', {
74 inputType: 'password',
75 name: 'password',
76 value: '',
77 fieldLabel: gettext('Password'),
78 allowBlank: false,
79 minLength: 5,
80 change: function(f, value) {
81 if (!me.rendered) {
82 return;
83 }
84 me.down('field[name=confirmpw]').validate();
85 }
86 });
87
88 me.sshkeyfield = Ext.createWidget('pvetextfield', {
89 name: 'ssh-public-keys',
90 value: '',
91 fieldLabel: gettext('SSH public key'),
92 allowBlank: true,
93 validator: function(value) {
94 if (value.length) {
95 var key = PVE.Parser.parseSSHKey(value);
96 if (!key) {
97 return "Failed to recognize ssh key";
98 }
99 me.down('field[name=password]').allowBlank = true;
100 } else {
101 me.down('field[name=password]').allowBlank = false;
102 }
103 me.down('field[name=password]').validate();
104 return true;
105 },
106 afterRender: function() {
107 if (!window.FileReader) {
108 // No FileReader support in this browser
109 return;
110 }
111 var cancel = function(ev) {
112 ev = ev.event;
113 if (ev.preventDefault) {
114 ev.preventDefault();
115 }
116 };
117 me.sshkeyfield.inputEl.on('dragover', cancel);
118 me.sshkeyfield.inputEl.on('dragenter', cancel);
119 me.sshkeyfield.inputEl.on('drop', function(ev) {
120 ev = ev.event;
121 if (ev.preventDefault) {
122 ev.preventDefault();
123 }
124 var files = ev.dataTransfer.files;
125 me.loadSSHKeyFromFile(files[0]);
126 });
127 }
128 });
129
130 var column2 = [
131 {
132 xtype: 'pvePoolSelector',
133 fieldLabel: gettext('Resource Pool'),
134 name: 'pool',
135 value: '',
136 allowBlank: true
137 },
138 passwordfield,
139 {
140 xtype: 'textfield',
141 inputType: 'password',
142 name: 'confirmpw',
143 value: '',
144 fieldLabel: gettext('Confirm password'),
145 allowBlank: true,
146 validator: function(value) {
147 var pw = me.down('field[name=password]').getValue();
148 if (pw !== value) {
149 return "Passwords does not match!";
150 }
151 return true;
152 }
153 },
154 me.sshkeyfield
155 ];
156
157 if (window.FileReader) {
158 column2.push({
159 xtype: 'filebutton',
160 name: 'file',
161 text: gettext('Load SSH Key File'),
162 listeners: {
163 change: function(btn, e, value) {
164 e = e.event;
165 me.loadSSHKeyFromFile(e.target.files[0]);
166 btn.reset();
167 }
168 }
169 });
170 }
171
172 Ext.applyIf(me, {
173 subject: gettext('LXC Container'),
174 items: [
175 {
176 xtype: 'inputpanel',
177 title: gettext('General'),
178 column1: [
179 {
180 xtype: 'pveNodeSelector',
181 name: 'nodename',
182 selectCurNode: true,
183 fieldLabel: gettext('Node'),
184 allowBlank: false,
185 onlineValidator: true,
186 listeners: {
187 change: function(f, value) {
188 tmplstoragesel.setNodename(value);
189 tmplsel.setStorage(undefined, value);
190 networkpanel.setNodename(value);
191 rootfspanel.setNodename(value);
192 }
193 }
194 },
195 {
196 xtype: 'pveVMIDSelector',
197 name: 'vmid',
198 value: '',
199 loadNextFreeVMID: true,
200 validateExists: false
201 },
202 {
203 xtype: 'pvetextfield',
204 name: 'hostname',
205 vtype: 'DnsName',
206 value: '',
207 fieldLabel: gettext('Hostname'),
208 skipEmptyText: true,
209 allowBlank: true
210 },
211 {
212 xtype: 'pvecheckbox',
213 name: 'unprivileged',
214 value: '',
215 fieldLabel: gettext('Unprivileged container')
216 }
217 ],
218 column2: column2,
219 onGetValues: function(values) {
220 delete values.confirmpw;
221 if (!values.pool) {
222 delete values.pool;
223 }
224 return values;
225 }
226 },
227 {
228 xtype: 'inputpanel',
229 title: gettext('Template'),
230 onlineHelp: 'pct_container_images',
231 column1: [ tmplstoragesel, tmplsel]
232 },
233 rootfspanel,
234 {
235 xtype: 'pveLxcCPUInputPanel',
236 title: gettext('CPU'),
237 insideWizard: true
238 },
239 {
240 xtype: 'pveLxcMemoryInputPanel',
241 title: gettext('Memory'),
242 insideWizard: true
243 },
244 networkpanel,
245 {
246 xtype: 'pveLxcDNSInputPanel',
247 title: gettext('DNS'),
248 insideWizard: true
249 },
250 {
251 title: gettext('Confirm'),
252 layout: 'fit',
253 items: [
254 {
255 title: gettext('Settings'),
256 xtype: 'grid',
257 store: summarystore,
258 columns: [
259 {header: 'Key', width: 150, dataIndex: 'key'},
260 {header: 'Value', flex: 1, dataIndex: 'value'}
261 ]
262 }
263 ],
264 listeners: {
265 show: function(panel) {
266 var form = me.down('form').getForm();
267 var kv = me.getValues();
268 var data = [];
269 Ext.Object.each(kv, function(key, value) {
270 if (key === 'delete' || key === 'tmplstorage') { // ignore
271 return;
272 }
273 if (key === 'password') { // don't show pw
274 return;
275 }
276 var html = Ext.htmlEncode(Ext.JSON.encode(value));
277 data.push({ key: key, value: value });
278 });
279 summarystore.suspendEvents();
280 summarystore.removeAll();
281 summarystore.add(data);
282 summarystore.sort();
283 summarystore.resumeEvents();
284 summarystore.fireEvent('refresh');
285 }
286 },
287 onSubmit: function() {
288 var kv = me.getValues();
289 delete kv['delete'];
290
291 var nodename = kv.nodename;
292 delete kv.nodename;
293 delete kv.tmplstorage;
294
295 if (!kv.password.length && kv['ssh-public-keys']) {
296 delete kv.password;
297 }
298
299 PVE.Utils.API2Request({
300 url: '/nodes/' + nodename + '/lxc',
301 waitMsgTarget: me,
302 method: 'POST',
303 params: kv,
304 success: function(response, opts){
305 var upid = response.result.data;
306
307 var win = Ext.create('PVE.window.TaskViewer', {
308 upid: upid
309 });
310 win.show();
311 me.close();
312 },
313 failure: function(response, opts) {
314 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
315 }
316 });
317 }
318 }
319 ]
320 });
321
322 me.callParent();
323 }
324 });
325
326
327