]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/HardwareView.js
6bbc090c64c965ca1f128104aa432222a66132e6
1 // fixme: howto avoid jslint type confusion?
2 /*jslint confusion: true */
3 Ext
.define('PVE.qemu.HardwareView', {
4 extend
: 'PVE.grid.PendingObjectGrid',
5 alias
: ['widget.PVE.qemu.HardwareView'],
7 onlineHelp
: 'qm_virtual_machines_settings',
9 renderKey: function(key
, metaData
, rec
, rowIndex
, colIndex
, store
) {
12 var rowdef
= rows
[key
] || {};
14 metaData
.tdAttr
= "valign=middle";
17 metaData
.tdCls
= rowdef
.tdCls
;
18 if (rowdef
.tdCls
== 'pve-itype-icon-storage') {
19 var value
= me
.getObjectValue(key
, '', true);
20 if (value
.match(/media=cdrom/)) {
21 metaData
.tdCls
= 'pve-itype-icon-cdrom';
22 return rowdef
.cdheader
;
26 return rowdef
.header
|| key
;
29 initComponent : function() {
33 var nodename
= me
.pveSelNode
.data
.node
;
35 throw "no node name specified";
38 var vmid
= me
.pveSelNode
.data
.vmid
;
40 throw "no VM ID specified";
43 var caps
= Ext
.state
.Manager
.get('GuiCap');
47 header
: gettext('Memory'),
48 editor
: caps
.vms
['VM.Config.Memory'] ? 'PVE.qemu.MemoryEdit' : undefined,
51 tdCls
: 'pve-itype-icon-memory',
52 renderer: function(value
, metaData
, record
) {
53 var balloon
= me
.getObjectValue('balloon');
55 return PVE
.Utils
.format_size(balloon
*1024*1024) + "/" +
56 PVE
.Utils
.format_size(value
*1024*1024);
59 return PVE
.Utils
.format_size(value
*1024*1024);
63 header
: gettext('Processors'),
65 editor
: (caps
.vms
['VM.Config.CPU'] || caps
.vms
['VM.Config.HWType']) ?
66 'PVE.qemu.ProcessorEdit' : undefined,
67 tdCls
: 'pve-itype-icon-processor',
69 multiKey
: ['sockets', 'cpu', 'cores', 'numa', 'vcpus', 'cpulimit', 'cpuunits'],
70 renderer: function(value
, metaData
, record
, rowIndex
, colIndex
, store
, pending
) {
72 var sockets
= me
.getObjectValue('sockets', 1, pending
);
73 var model
= me
.getObjectValue('cpu', undefined, pending
);
74 var cores
= me
.getObjectValue('cores', 1, pending
);
75 var numa
= me
.getObjectValue('numa', undefined, pending
);
76 var vcpus
= me
.getObjectValue('vcpus', undefined, pending
);
77 var cpulimit
= me
.getObjectValue('cpulimit', undefined, pending
);
78 var cpuunits
= me
.getObjectValue('cpuunits', undefined, pending
);
80 var res
= (sockets
*cores
) + ' (' + sockets
+ ' sockets, ' + cores
+ ' cores)';
83 res
+= ' [' + model
+ ']';
87 res
+= ' [numa=' + numa
+']';
91 res
+= ' [vcpus=' + vcpus
+']';
95 res
+= ' [cpulimit=' + cpulimit
+']';
99 res
+= ' [cpuunits=' + cpuunits
+']';
106 header
: gettext('Keyboard Layout'),
108 editor
: caps
.vms
['VM.Config.Options'] ? 'PVE.qemu.KeyboardEdit' : undefined,
109 tdCls
: 'pve-itype-icon-keyboard',
111 renderer
: PVE
.Utils
.render_kvm_language
114 header
: gettext('Display'),
115 editor
: caps
.vms
['VM.Config.HWType'] ? 'PVE.qemu.DisplayEdit' : undefined,
117 tdCls
: 'pve-itype-icon-display',
119 renderer
: PVE
.Utils
.render_kvm_vga_driver
151 for (i
= 0; i
< 4; i
++) {
155 tdCls
: 'pve-itype-icon-storage',
156 editor
: 'PVE.qemu.HDEdit',
157 never_delete
: caps
.vms
['VM.Config.Disk'] ? false : true,
158 header
: gettext('Hard Disk') + ' (' + confid
+')',
159 cdheader
: gettext('CD/DVD Drive') + ' (' + confid
+')'
162 for (i
= 0; i
< 6; i
++) {
166 tdCls
: 'pve-itype-icon-storage',
167 editor
: 'PVE.qemu.HDEdit',
168 never_delete
: caps
.vms
['VM.Config.Disk'] ? false : true,
169 header
: gettext('Hard Disk') + ' (' + confid
+')',
170 cdheader
: gettext('CD/DVD Drive') + ' (' + confid
+')'
173 for (i
= 0; i
< 16; i
++) {
177 tdCls
: 'pve-itype-icon-storage',
178 editor
: 'PVE.qemu.HDEdit',
179 never_delete
: caps
.vms
['VM.Config.Disk'] ? false : true,
180 header
: gettext('Hard Disk') + ' (' + confid
+')',
181 cdheader
: gettext('CD/DVD Drive') + ' (' + confid
+')'
184 for (i
= 0; i
< 16; i
++) {
185 confid
= "virtio" + i
;
188 tdCls
: 'pve-itype-icon-storage',
189 editor
: 'PVE.qemu.HDEdit',
190 never_delete
: caps
.vms
['VM.Config.Disk'] ? false : true,
191 header
: gettext('Hard Disk') + ' (' + confid
+')',
192 cdheader
: gettext('CD/DVD Drive') + ' (' + confid
+')'
195 for (i
= 0; i
< 32; i
++) {
199 tdCls
: 'pve-itype-icon-network',
200 editor
: caps
.vms
['VM.Config.Network'] ? 'PVE.qemu.NetworkEdit' : undefined,
201 never_delete
: caps
.vms
['VM.Config.Network'] ? false : true,
202 header
: gettext('Network Device') + ' (' + confid
+')'
207 tdCls
: 'pve-itype-icon-storage',
209 never_delete
: caps
.vms
['VM.Config.Disk'] ? false : true,
210 header
: gettext('EFI Disk')
212 for (i
= 0; i
< 5; i
++) {
216 tdCls
: 'pve-itype-icon-usb',
218 header
: gettext('USB Device') + ' (' + confid
+ ')'
221 for (i
= 0; i
< 8; i
++) {
222 rows
["unused" + i
] = {
224 tdCls
: 'pve-itype-icon-storage',
225 editor
: caps
.vms
['VM.Config.Disk'] ? 'PVE.qemu.HDEdit' : undefined,
226 header
: gettext('Unused Disk') + ' ' + i
230 var sorterFn = function(rec1
, rec2
) {
231 var v1
= rec1
.data
.key
;
232 var v2
= rec2
.data
.key
;
233 var g1
= rows
[v1
].group
|| 0;
234 var g2
= rows
[v2
].group
|| 0;
237 (g1
> g2
? 1 : -1) : (v1
> v2
? 1 : (v1
< v2
? -1 : 0));
240 var reload = function() {
244 var baseurl
= 'nodes/' + nodename
+ '/qemu/' + vmid
+ '/config';
246 var sm
= Ext
.create('Ext.selection.RowModel', {});
248 var run_editor = function() {
249 var rec
= sm
.getSelection()[0];
254 var rowdef
= rows
[rec
.data
.key
];
255 if (!rowdef
.editor
) {
259 var editor
= rowdef
.editor
;
260 if (rowdef
.tdCls
== 'pve-itype-icon-storage') {
261 var value
= me
.getObjectValue(rec
.data
.key
, '', true);
262 if (value
.match(/media=cdrom/)) {
263 editor
= 'PVE.qemu.CDEdit';
269 if (Ext
.isString(editor
)) {
270 win
= Ext
.create(editor
, {
271 pveSelNode
: me
.pveSelNode
,
272 confid
: rec
.data
.key
,
273 url
: '/api2/extjs/' + baseurl
276 var config
= Ext
.apply({
277 pveSelNode
: me
.pveSelNode
,
278 confid
: rec
.data
.key
,
279 url
: '/api2/extjs/' + baseurl
281 win
= Ext
.createWidget(rowdef
.editor
.xtype
, config
);
286 win
.on('destroy', reload
);
289 var run_diskthrottle = function() {
290 var rec
= sm
.getSelection()[0];
295 var win
= Ext
.create('PVE.qemu.HDThrottle', {
296 pveSelNode
: me
.pveSelNode
,
297 confid
: rec
.data
.key
,
298 url
: '/api2/extjs/' + baseurl
302 win
.on('destroy', reload
);
305 var run_resize = function() {
306 var rec
= sm
.getSelection()[0];
311 var win
= Ext
.create('PVE.window.HDResize', {
319 win
.on('destroy', reload
);
322 var run_cpuoptions = function() {
323 var sockets
= me
.getObjectValue('sockets', 1);
324 var cores
= me
.getObjectValue('cores', 1);
326 var win
= Ext
.create('PVE.qemu.CPUOptions', {
327 maxvcpus
: sockets
* cores
,
329 pveSelNode
: me
.pveSelNode
,
330 url
: '/api2/extjs/' + baseurl
335 win
.on('destroy', reload
);
338 var run_move = function() {
339 var rec
= sm
.getSelection()[0];
344 var win
= Ext
.create('PVE.window.HDMove', {
352 win
.on('destroy', reload
);
355 var edit_btn
= new PVE
.button
.Button({
356 text
: gettext('Edit'),
362 var resize_btn
= new PVE
.button
.Button({
363 text
: gettext('Resize disk'),
369 var move_btn
= new PVE
.button
.Button({
370 text
: gettext('Move disk'),
376 var diskthrottle_btn
= new PVE
.button
.Button({
377 text
: gettext('Disk Throttle'),
380 handler
: run_diskthrottle
383 var cpuoptions_btn
= new Ext
.Button({
384 text
: gettext('CPU options'),
385 handler
: run_cpuoptions
388 var remove_btn
= new PVE
.button
.Button({
389 text
: gettext('Remove'),
393 confirmMsg: function(rec
) {
394 var msg
= Ext
.String
.format(gettext('Are you sure you want to remove entry {0}'),
395 "'" + me
.renderKey(rec
.data
.key
, {}, rec
) + "'");
396 if (rec
.data
.key
.match(/^unused\d+$/)) {
397 msg
+= " " + gettext('This will permanently erase all data.');
402 handler: function(b
, e
, rec
) {
403 PVE
.Utils
.API2Request({
404 url
: '/api2/extjs/' + baseurl
,
408 'delete': rec
.data
.key
410 callback: function() {
413 failure: function (response
, opts
) {
414 Ext
.Msg
.alert('Error', response
.htmlStatus
);
420 var revert_btn
= new PVE
.button
.Button({
421 text
: gettext('Revert'),
424 handler: function(b
, e
, rec
) {
425 var rowdef
= me
.rows
[rec
.data
.key
] || {};
426 var keys
= rowdef
.multiKey
|| [ rec
.data
.key
];
427 var revert
= keys
.join(',');
428 PVE
.Utils
.API2Request({
429 url
: '/api2/extjs/' + baseurl
,
435 callback: function() {
438 failure: function (response
, opts
) {
439 Ext
.Msg
.alert('Error',response
.htmlStatus
);
445 var efidisk_menuitem
= Ext
.create('Ext.menu.Item',{
446 text
: gettext('EFI Disk'),
447 iconCls
: 'pve-itype-icon-storage',
448 disabled
: !caps
.vms
['VM.Config.Disk'],
449 handler: function() {
451 var rstoredata
= me
.rstore
.getData().map
;
452 // check if ovmf is configured
453 if (rstoredata
.bios
&& rstoredata
.bios
.data
.value
=== 'ovmf') {
454 var win
= Ext
.create('PVE.qemu.EFIDiskEdit', {
455 url
: '/api2/extjs/' + baseurl
,
456 pveSelNode
: me
.pveSelNode
458 win
.on('destroy', reload
);
461 Ext
.Msg
.alert('Error',gettext('Please select OVMF(UEFI) as BIOS first.'));
467 var set_button_status = function() {
468 var sm
= me
.getSelectionModel();
469 var rec
= sm
.getSelection()[0];
471 // disable button when we have an efidisk already
472 // disable is ok in this case, because you can instantly
473 // see that there is already one
474 efidisk_menuitem
.setDisabled(me
.rstore
.getData().map
.efidisk0
!== undefined);
477 remove_btn
.disable();
479 resize_btn
.disable();
481 diskthrottle_btn
.disable();
482 revert_btn
.disable();
485 var key
= rec
.data
.key
;
486 var value
= rec
.data
.value
;
487 var rowdef
= rows
[key
];
489 var pending
= rec
.data
['delete'] || me
.hasPendingChanges(key
);
490 var isDisk
= !key
.match(/^unused\d+/) &&
491 rowdef
.tdCls
== 'pve-itype-icon-storage' &&
492 (value
&& !value
.match(/media=cdrom/));
494 var isEfi
= (key
=== 'efidisk0');
497 remove_btn
.setDisabled(rec
.data
['delete'] || (rowdef
.never_delete
=== true));
499 edit_btn
.setDisabled(rec
.data
['delete'] || !rowdef
.editor
);
501 resize_btn
.setDisabled(pending
|| !isDisk
);
503 move_btn
.setDisabled(pending
|| !isDisk
);
505 diskthrottle_btn
.setDisabled(pending
|| !isDisk
|| isEfi
);
507 revert_btn
.setDisabled(!pending
);
512 url
: '/api2/json/' + 'nodes/' + nodename
+ '/qemu/' + vmid
+ '/pending',
517 text
: gettext('Add'),
518 menu
: new Ext
.menu
.Menu({
521 text
: gettext('Hard Disk'),
522 iconCls
: 'pve-itype-icon-storage',
523 disabled
: !caps
.vms
['VM.Config.Disk'],
524 handler: function() {
525 var win
= Ext
.create('PVE.qemu.HDEdit', {
526 url
: '/api2/extjs/' + baseurl
,
527 pveSelNode
: me
.pveSelNode
529 win
.on('destroy', reload
);
534 text
: gettext('CD/DVD Drive'),
535 iconCls
: 'pve-itype-icon-cdrom',
536 disabled
: !caps
.vms
['VM.Config.Disk'],
537 handler: function() {
538 var win
= Ext
.create('PVE.qemu.CDEdit', {
539 url
: '/api2/extjs/' + baseurl
,
540 pveSelNode
: me
.pveSelNode
542 win
.on('destroy', reload
);
547 text
: gettext('Network Device'),
548 iconCls
: 'pve-itype-icon-network',
549 disabled
: !caps
.vms
['VM.Config.Network'],
550 handler: function() {
551 var win
= Ext
.create('PVE.qemu.NetworkEdit', {
552 url
: '/api2/extjs/' + baseurl
,
553 pveSelNode
: me
.pveSelNode
555 win
.on('destroy', reload
);
574 itemdblclick
: run_editor
,
575 selectionchange
: set_button_status
581 me
.on('activate', me
.rstore
.startUpdate
);
582 me
.on('destroy', me
.rstore
.stopUpdate
);
584 me
.mon(me
.rstore
, 'refresh', function() {