X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=www%2Fmanager6%2Fqemu%2FPCIEdit.js;h=2f67aece9125a7f61e364f3e852d262e7c4fde7f;hb=refs%2Fheads%2Fmaster;hp=e1c6aea77f674a2eedce8c1ad4674d19fd5f4e5c;hpb=a7ec3666b16dde68d29a99518dd2abf0756d0ddd;p=pve-manager.git diff --git a/www/manager6/qemu/PCIEdit.js b/www/manager6/qemu/PCIEdit.js index e1c6aea7..8cef1b10 100644 --- a/www/manager6/qemu/PCIEdit.js +++ b/www/manager6/qemu/PCIEdit.js @@ -1,73 +1,157 @@ Ext.define('PVE.qemu.PCIInputPanel', { extend: 'Proxmox.panel.InputPanel', - onlineHelp: 'qm_pci_passthrough', + onlineHelp: 'qm_pci_passthrough_vm_config', - setVMConfig: function(vmconfig) { - var me = this; - me.vmconfig = vmconfig; + controller: { + xclass: 'Ext.app.ViewController', + + setVMConfig: function(vmconfig) { + let me = this; + let view = me.getView(); + me.vmconfig = vmconfig; - var hostpci = me.vmconfig[me.confid] || ''; + let hostpci = me.vmconfig[view.confid] || ''; - var values = PVE.Parser.parsePropertyString(hostpci, 'host'); - if (values.host) { - if (!values.host.match(/^[0-9a-f]{4}:/i)) { // add optional domain - values.host = "0000:" + values.host; + let values = PVE.Parser.parsePropertyString(hostpci, 'host'); + if (values.host) { + if (!values.host.match(/^[0-9a-f]{4}:/i)) { // add optional domain + values.host = "0000:" + values.host; + } + if (values.host.length < 11) { // 0000:00:00 format not 0000:00:00.0 + values.host += ".0"; + values.multifunction = true; + } + values.type = 'raw'; + } else if (values.mapping) { + values.type = 'mapped'; } - if (values.host.length < 11) { // 0000:00:00 format not 0000:00:00.0 - values.host += ".0"; - values.multifunction = true; + + values['x-vga'] = PVE.Parser.parseBoolean(values['x-vga'], 0); + values.pcie = PVE.Parser.parseBoolean(values.pcie, 0); + values.rombar = PVE.Parser.parseBoolean(values.rombar, 1); + + view.setValues(values); + if (!me.vmconfig.machine || me.vmconfig.machine.indexOf('q35') === -1) { + // machine is not set to some variant of q35, so we disable pcie + let pcie = me.lookup('pcie'); + pcie.setDisabled(true); + pcie.setBoxLabel(gettext('Q35 only')); } - } - values['x-vga'] = PVE.Parser.parseBoolean(values['x-vga'], 0); - values.pcie = PVE.Parser.parseBoolean(values.pcie, 0); - values.rombar = PVE.Parser.parseBoolean(values.rombar, 1); + if (values.romfile) { + me.lookup('romfile').setVisible(true); + } + }, - me.setValues(values); - if (!me.vmconfig.machine || me.vmconfig.machine.indexOf('q35') === -1) { - // machine is not set to some variant of q35, so we disable pcie - var pcie = me.down('field[name=pcie]'); - pcie.setDisabled(true); - pcie.setBoxLabel(gettext('Q35 only')); - } + selectorEnable: function(selector) { + let me = this; + me.pciDevChange(selector, selector.getValue()); + }, - if (values.romfile) { - me.down('field[name=romfile]').setVisible(true); - } - }, + pciDevChange: function(pcisel, value) { + let me = this; + let mdevfield = me.lookup('mdev'); + if (!value) { + if (!pcisel.isDisabled()) { + mdevfield.setDisabled(true); + } + return; + } + let pciDev = pcisel.getStore().getById(value); - onGetValues: function(values) { - let me = this; - if (!me.confid) { - for (let i = 0; i < 5; i++) { - if (!me.vmconfig['hostpci' + i.toString()]) { - me.confid = 'hostpci' + i.toString(); - break; + mdevfield.setDisabled(!pciDev || !pciDev.data.mdev); + if (!pciDev) { + return; + } + + let path = value; + if (pciDev.data.map) { + // find local mapping + for (const entry of pciDev.data.map) { + let mapping = PVE.Parser.parsePropertyString(entry); + if (mapping.node === pcisel.up('inputpanel').nodename) { + path = mapping.path.split(';')[0]; + break; + } + } + if (path.indexOf('.') === -1) { + path += '.0'; } } - // FIXME: what if no confid was found?? - } - values.host.replace(/^0000:/, ''); // remove optional '0000' domain - if (values.multifunction) { - values.host = values.host.substring(0, values.host.indexOf('.')); // skip the '.X' - delete values.multifunction; - } + if (pciDev.data.mdev) { + mdevfield.setPciID(path); + } + if (pcisel.reference === 'selector') { + let iommu = pciDev.data.iommugroup; + if (iommu === -1) { + return; + } + // try to find out if there are more devices in that iommu group + let id = path.substring(0, 5); // 00:00 + let count = 0; + pcisel.getStore().each(({ data }) => { + if (data.iommugroup === iommu && data.id.substring(0, 5) !== id) { + count++; + return false; + } + return true; + }); + me.lookup('group_warning').setVisible(count > 0); + } + }, - if (values.rombar) { - delete values.rombar; - } else { - values.rombar = 0; - } + onGetValues: function(values) { + let me = this; + let view = me.getView(); + if (!view.confid) { + for (let i = 0; i < PVE.Utils.hardware_counts.hostpci; i++) { + if (!me.vmconfig['hostpci' + i.toString()]) { + view.confid = 'hostpci' + i.toString(); + break; + } + } + // FIXME: what if no confid was found?? + } - if (!values.romfile) { - delete values.romfile; - } + values.host?.replace(/^0000:/, ''); // remove optional '0000' domain + + if (values.multifunction && values.host) { + values.host = values.host.substring(0, values.host.indexOf('.')); // skip the '.X' + delete values.multifunction; + } + + if (values.rombar) { + delete values.rombar; + } else { + values.rombar = 0; + } + + if (!values.romfile) { + delete values.romfile; + } + + delete values.type; + + let ret = {}; + ret[view.confid] = PVE.Parser.printPropertyString(values, 'host'); + return ret; + }, + }, - let ret = {}; - ret[me.confid] = PVE.Parser.printPropertyString(values, 'host'); - return ret; + viewModel: { + data: { + isMapped: true, + }, + }, + + setVMConfig: function(vmconfig) { + return this.getController().setVMConfig(vmconfig); + }, + + onGetValues: function(values) { + return this.getController().onGetValues(values); }, initComponent: function() { @@ -78,78 +162,97 @@ Ext.define('PVE.qemu.PCIInputPanel', { throw "no node name specified"; } + me.columnT = [ + { + xtype: 'displayfield', + reference: 'iommu_warning', + hidden: true, + columnWidth: 1, + padding: '0 0 10 0', + value: 'No IOMMU detected, please activate it.' + + 'See Documentation for further information.', + userCls: 'pmx-hint', + }, + { + xtype: 'displayfield', + reference: 'group_warning', + hidden: true, + columnWidth: 1, + padding: '0 0 10 0', + itemId: 'iommuwarning', + value: 'The selected Device is not in a seperate IOMMU group, make sure this is intended.', + userCls: 'pmx-hint', + }, + ]; + me.column1 = [ + { + xtype: 'radiofield', + name: 'type', + inputValue: 'mapped', + boxLabel: gettext('Mapped Device'), + bind: { + value: '{isMapped}', + }, + }, + { + xtype: 'pvePCIMapSelector', + fieldLabel: gettext('Device'), + reference: 'mapped_selector', + name: 'mapping', + labelAlign: 'right', + nodename: me.nodename, + allowBlank: false, + bind: { + disabled: '{!isMapped}', + }, + listeners: { + change: 'pciDevChange', + enable: 'selectorEnable', + }, + }, + { + xtype: 'radiofield', + name: 'type', + inputValue: 'raw', + checked: true, + boxLabel: gettext('Raw Device'), + }, { xtype: 'pvePCISelector', fieldLabel: gettext('Device'), name: 'host', + reference: 'selector', nodename: me.nodename, + labelAlign: 'right', allowBlank: false, + disabled: true, + bind: { + disabled: '{isMapped}', + }, onLoadCallBack: function(store, records, success) { if (!success || !records.length) { return; } - if (records.every((val) => val.data.iommugroup === -1)) { // no IOMMU groups - let warning = Ext.create('Ext.form.field.Display', { - columnWidth: 1, - padding: '0 0 10 0', - value: 'No IOMMU detected, please activate it.' + - 'See Documentation for further information.', - userCls: 'pmx-hint', - }); - me.items.insert(0, warning); - me.updateLayout(); // insert does not trigger that - } + me.lookup('iommu_warning').setVisible( + records.every((val) => val.data.iommugroup === -1), + ); }, listeners: { - change: function(pcisel, value) { - if (!value) { - return; - } - let pciDev = pcisel.getStore().getById(value); - let mdevfield = me.down('field[name=mdev]'); - mdevfield.setDisabled(!pciDev || !pciDev.data.mdev); - if (!pciDev) { - return; - } - if (pciDev.data.mdev) { - mdevfield.setPciID(value); - } - let iommu = pciDev.data.iommugroup; - if (iommu === -1) { - return; - } - // try to find out if there are more devices in that iommu group - let id = pciDev.data.id.substring(0, 5); // 00:00 - let count = 0; - pcisel.getStore().each(({ data }) => { - if (data.iommugroup === iommu && data.id.substring(0, 5) !== id) { - count++; - return false; - } - return true; - }); - let warning = me.down('#iommuwarning'); - if (count && !warning) { - warning = Ext.create('Ext.form.field.Display', { - columnWidth: 1, - padding: '0 0 10 0', - itemId: 'iommuwarning', - value: 'The selected Device is not in a seperate IOMMU group, make sure this is intended.', - userCls: 'pmx-hint', - }); - me.items.insert(0, warning); - me.updateLayout(); // insert does not trigger that - } else if (!count && warning) { - me.remove(warning); - } - }, + change: 'pciDevChange', + enable: 'selectorEnable', }, }, { xtype: 'proxmoxcheckbox', fieldLabel: gettext('All Functions'), + reference: 'all_functions', + disabled: true, + labelAlign: 'right', name: 'multifunction', + bind: { + disabled: '{isMapped}', + }, }, ]; @@ -157,6 +260,7 @@ Ext.define('PVE.qemu.PCIInputPanel', { { xtype: 'pveMDevSelector', name: 'mdev', + reference: 'mdev', disabled: true, fieldLabel: gettext('MDev Type'), nodename: me.nodename, @@ -188,16 +292,54 @@ Ext.define('PVE.qemu.PCIInputPanel', { submitValue: true, hidden: true, fieldLabel: 'ROM-File', + reference: 'romfile', name: 'romfile', }, + { + xtype: 'textfield', + name: 'vendor-id', + fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Vendor')), + emptyText: gettext('From Device'), + vtype: 'PciId', + allowBlank: true, + submitEmpty: false, + }, + { + xtype: 'textfield', + name: 'device-id', + fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Device')), + emptyText: gettext('From Device'), + vtype: 'PciId', + allowBlank: true, + submitEmpty: false, + }, ]; me.advancedColumn2 = [ { xtype: 'proxmoxcheckbox', fieldLabel: 'PCI-Express', + reference: 'pcie', name: 'pcie', }, + { + xtype: 'textfield', + name: 'sub-vendor-id', + fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Sub-Vendor')), + emptyText: gettext('From Device'), + vtype: 'PciId', + allowBlank: true, + submitEmpty: false, + }, + { + xtype: 'textfield', + name: 'sub-device-id', + fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Sub-Device')), + emptyText: gettext('From Device'), + vtype: 'PciId', + allowBlank: true, + submitEmpty: false, + }, ]; me.callParent();