]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/HDEdit.js
gui: add system panel to the vm creation wizard
[pve-manager.git] / www / manager6 / qemu / HDEdit.js
1 /*jslint confusion: true */
2 /* 'change' property is assigned a string and then a function */
3 Ext.define('PVE.qemu.HDInputPanel', {
4 extend: 'Proxmox.panel.InputPanel',
5 alias: 'widget.pveQemuHDInputPanel',
6 onlineHelp: 'qm_hard_disk',
7
8 insideWizard: false,
9
10 unused: false, // ADD usused disk imaged
11
12 vmconfig: {}, // used to select usused disks
13
14 controller: {
15
16 xclass: 'Ext.app.ViewController',
17
18 onControllerChange: function(field) {
19 var value = field.getValue();
20
21 var allowIOthread = value.match(/^(virtio|scsi)/);
22 this.lookup('iothread').setDisabled(!allowIOthread);
23 if (!allowIOthread) {
24 this.lookup('iothread').setValue(false);
25 }
26
27 var virtio = value.match(/^virtio/);
28 this.lookup('discard').setDisabled(virtio);
29 this.lookup('ssd').setDisabled(virtio);
30 if (virtio) {
31 this.lookup('discard').setValue(false);
32 this.lookup('ssd').setValue(false);
33 }
34
35 this.lookup('scsiController').setVisible(value.match(/^scsi/));
36 },
37
38 control: {
39 'field[name=controller]': {
40 change: 'onControllerChange',
41 afterrender: 'onControllerChange'
42 },
43 'field[name=iothread]' : {
44 change: function(f, value) {
45 if (!this.getView().insideWizard) {
46 return;
47 }
48 var vmScsiType = value ? 'virtio-scsi-single': 'virtio-scsi-pci';
49 this.lookupReference('scsiController').setValue(vmScsiType);
50 }
51 }
52 }
53 },
54
55 onGetValues: function(values) {
56 var me = this;
57
58 var params = {};
59 var confid = me.confid || (values.controller + values.deviceid);
60
61 if (me.unused) {
62 me.drive.file = me.vmconfig[values.unusedId];
63 confid = values.controller + values.deviceid;
64 } else if (me.isCreate) {
65 if (values.hdimage) {
66 me.drive.file = values.hdimage;
67 } else {
68 me.drive.file = values.hdstorage + ":" + values.disksize;
69 }
70 me.drive.format = values.diskformat;
71 }
72
73 if (values.nobackup) {
74 me.drive.backup = 'no';
75 } else {
76 delete me.drive.backup;
77 }
78
79 if (values.noreplicate) {
80 me.drive.replicate = 'no';
81 } else {
82 delete me.drive.replicate;
83 }
84
85 if (values.discard) {
86 me.drive.discard = 'on';
87 } else {
88 delete me.drive.discard;
89 }
90
91 if (values.ssd) {
92 me.drive.ssd = 'on';
93 } else {
94 delete me.drive.ssd;
95 }
96
97 if (values.iothread) {
98 me.drive.iothread = 'on';
99 } else {
100 delete me.drive.iothread;
101 }
102
103 if (values.cache) {
104 me.drive.cache = values.cache;
105 } else {
106 delete me.drive.cache;
107 }
108
109 var names = ['mbps_rd', 'mbps_wr', 'iops_rd', 'iops_wr'];
110 Ext.Array.each(names, function(name) {
111 if (values[name]) {
112 me.drive[name] = values[name];
113 } else {
114 delete me.drive[name];
115 }
116 var burst_name = name + '_max';
117 if (values[burst_name] && values[name]) {
118 me.drive[burst_name] = values[burst_name];
119 } else {
120 delete me.drive[burst_name];
121 }
122 });
123
124
125 params[confid] = PVE.Parser.printQemuDrive(me.drive);
126
127 return params;
128 },
129
130 setVMConfig: function(vmconfig) {
131 var me = this;
132
133 me.vmconfig = vmconfig;
134
135 if (me.bussel) {
136 me.bussel.setVMConfig(vmconfig);
137 me.scsiController.setValue(vmconfig.scsihw);
138 }
139 if (me.unusedDisks) {
140 var disklist = [];
141 Ext.Object.each(vmconfig, function(key, value) {
142 if (key.match(/^unused\d+$/)) {
143 disklist.push([key, value]);
144 }
145 });
146 me.unusedDisks.store.loadData(disklist);
147 me.unusedDisks.setValue(me.confid);
148 }
149 },
150
151 setDrive: function(drive) {
152 var me = this;
153
154 me.drive = drive;
155
156 var values = {};
157 var match = drive.file.match(/^([^:]+):/);
158 if (match) {
159 values.hdstorage = match[1];
160 }
161
162 values.hdimage = drive.file;
163 values.nobackup = !PVE.Parser.parseBoolean(drive.backup, 1);
164 values.noreplicate = !PVE.Parser.parseBoolean(drive.replicate, 1);
165 values.diskformat = drive.format || 'raw';
166 values.cache = drive.cache || '__default__';
167 values.discard = (drive.discard === 'on');
168 values.ssd = PVE.Parser.parseBoolean(drive.ssd);
169 values.iothread = PVE.Parser.parseBoolean(drive.iothread);
170
171 values.mbps_rd = drive.mbps_rd;
172 values.mbps_wr = drive.mbps_wr;
173 values.iops_rd = drive.iops_rd;
174 values.iops_wr = drive.iops_wr;
175 values.mbps_rd_max = drive.mbps_rd_max;
176 values.mbps_wr_max = drive.mbps_wr_max;
177 values.iops_rd_max = drive.iops_rd_max;
178 values.iops_wr_max = drive.iops_wr_max;
179
180 me.setValues(values);
181 },
182
183 setNodename: function(nodename) {
184 var me = this;
185 me.down('#hdstorage').setNodename(nodename);
186 me.down('#hdimage').setStorage(undefined, nodename);
187 },
188
189 initComponent : function() {
190 var me = this;
191
192 var labelWidth = 140;
193
194 me.drive = {};
195
196 me.column1 = [];
197 me.column2 = [];
198
199 me.advancedColumn1 = [];
200 me.advancedColumn2 = [];
201
202 if (!me.confid || me.unused) {
203 me.bussel = Ext.create('PVE.form.ControllerSelector', {
204 vmconfig: me.insideWizard ? {ide2: 'cdrom'} : {}
205 });
206 me.column1.push(me.bussel);
207
208 me.scsiController = Ext.create('Ext.form.field.Display', {
209 fieldLabel: gettext('SCSI Controller'),
210 reference: 'scsiController',
211 bind: me.insideWizard ? {
212 value: '{current.scsihw}'
213 } : undefined,
214 renderer: PVE.Utils.render_scsihw,
215 submitValue: false,
216 hidden: true
217 });
218 me.column1.push(me.scsiController);
219 }
220
221 if (me.unused) {
222 me.unusedDisks = Ext.create('Proxmox.form.KVComboBox', {
223 name: 'unusedId',
224 fieldLabel: gettext('Disk image'),
225 matchFieldWidth: false,
226 listConfig: {
227 width: 350
228 },
229 data: [],
230 allowBlank: false
231 });
232 me.column1.push(me.unusedDisks);
233 } else if (me.isCreate) {
234 me.column1.push({
235 xtype: 'pveDiskStorageSelector',
236 storageContent: 'images',
237 name: 'disk',
238 nodename: me.nodename,
239 autoSelect: me.insideWizard
240 });
241 } else {
242 me.column1.push({
243 xtype: 'textfield',
244 disabled: true,
245 submitValue: false,
246 fieldLabel: gettext('Disk image'),
247 name: 'hdimage'
248 });
249 }
250
251 me.column2.push(
252 {
253 xtype: 'CacheTypeSelector',
254 name: 'cache',
255 value: '__default__',
256 fieldLabel: gettext('Cache')
257 },
258 {
259 xtype: 'proxmoxcheckbox',
260 fieldLabel: gettext('Discard'),
261 disabled: me.confid && me.confid.match(/^virtio/),
262 reference: 'discard',
263 name: 'discard'
264 }
265 );
266
267 me.advancedColumn1.push(
268 {
269 xtype: 'proxmoxcheckbox',
270 disabled: me.confid && me.confid.match(/^virtio/),
271 fieldLabel: gettext('SSD emulation'),
272 labelWidth: labelWidth,
273 name: 'ssd',
274 reference: 'ssd'
275 },
276 {
277 xtype: 'proxmoxcheckbox',
278 disabled: me.confid && !me.confid.match(/^(virtio|scsi)/),
279 fieldLabel: 'IO thread',
280 labelWidth: labelWidth,
281 reference: 'iothread',
282 name: 'iothread'
283 },
284 {
285 xtype: 'numberfield',
286 name: 'mbps_rd',
287 minValue: 1,
288 step: 1,
289 fieldLabel: gettext('Read limit') + ' (MB/s)',
290 labelWidth: labelWidth,
291 emptyText: gettext('unlimited')
292 },
293 {
294 xtype: 'numberfield',
295 name: 'mbps_wr',
296 minValue: 1,
297 step: 1,
298 fieldLabel: gettext('Write limit') + ' (MB/s)',
299 labelWidth: labelWidth,
300 emptyText: gettext('unlimited')
301 },
302 {
303 xtype: 'proxmoxintegerfield',
304 name: 'iops_rd',
305 minValue: 10,
306 step: 10,
307 fieldLabel: gettext('Read limit') + ' (ops/s)',
308 labelWidth: labelWidth,
309 emptyText: gettext('unlimited')
310 },
311 {
312 xtype: 'proxmoxintegerfield',
313 name: 'iops_wr',
314 minValue: 10,
315 step: 10,
316 fieldLabel: gettext('Write limit') + ' (ops/s)',
317 labelWidth: labelWidth,
318 emptyText: gettext('unlimited')
319 }
320 );
321
322 me.advancedColumn2.push(
323 {
324 xtype: 'proxmoxcheckbox',
325 fieldLabel: gettext('No backup'),
326 labelWidth: labelWidth,
327 name: 'nobackup'
328 },
329 {
330 xtype: 'proxmoxcheckbox',
331 fieldLabel: gettext('Skip replication'),
332 labelWidth: labelWidth,
333 name: 'noreplicate'
334 },
335 {
336 xtype: 'numberfield',
337 name: 'mbps_rd_max',
338 minValue: 1,
339 step: 1,
340 fieldLabel: gettext('Read max burst') + ' (MB)',
341 labelWidth: labelWidth,
342 emptyText: gettext('default')
343 },
344 {
345 xtype: 'numberfield',
346 name: 'mbps_wr_max',
347 minValue: 1,
348 step: 1,
349 fieldLabel: gettext('Write max burst') + ' (MB)',
350 labelWidth: labelWidth,
351 emptyText: gettext('default')
352 },
353 {
354 xtype: 'proxmoxintegerfield',
355 name: 'iops_rd_max',
356 minValue: 10,
357 step: 10,
358 fieldLabel: gettext('Read max burst') + ' (ops)',
359 labelWidth: labelWidth,
360 emptyText: gettext('default')
361 },
362 {
363 xtype: 'proxmoxintegerfield',
364 name: 'iops_wr_max',
365 minValue: 10,
366 step: 10,
367 fieldLabel: gettext('Write max burst') + ' (ops)',
368 labelWidth: labelWidth,
369 emptyText: gettext('default')
370 }
371 );
372
373 me.callParent();
374 }
375 });
376 /*jslint confusion: false */
377
378 Ext.define('PVE.qemu.HDEdit', {
379 extend: 'Proxmox.window.Edit',
380
381 isAdd: true,
382
383 backgroundDelay: 5,
384
385 initComponent : function() {
386 var me = this;
387
388 var nodename = me.pveSelNode.data.node;
389 if (!nodename) {
390 throw "no node name specified";
391 }
392
393 var unused = me.confid && me.confid.match(/^unused\d+$/);
394
395 me.isCreate = me.confid ? unused : true;
396
397 var ipanel = Ext.create('PVE.qemu.HDInputPanel', {
398 confid: me.confid,
399 nodename: nodename,
400 unused: unused,
401 isCreate: me.isCreate
402 });
403
404 var subject;
405 if (unused) {
406 me.subject = gettext('Unused Disk');
407 } else if (me.isCreate) {
408 me.subject = gettext('Hard Disk');
409 } else {
410 me.subject = gettext('Hard Disk') + ' (' + me.confid + ')';
411 }
412
413 me.items = [ ipanel ];
414
415 me.callParent();
416 /*jslint confusion: true*/
417 /* 'data' is assigned an empty array in same file, and here we
418 * use it like an object
419 */
420 me.load({
421 success: function(response, options) {
422 ipanel.setVMConfig(response.result.data);
423 if (me.confid) {
424 var value = response.result.data[me.confid];
425 var drive = PVE.Parser.parseQemuDrive(me.confid, value);
426 if (!drive) {
427 Ext.Msg.alert(gettext('Error'), 'Unable to parse drive options');
428 me.close();
429 return;
430 }
431 ipanel.setDrive(drive);
432 me.isValid(); // trigger validation
433 }
434 }
435 });
436 /*jslint confusion: false*/
437 }
438 });