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