]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/PCIEdit.js
ui: fix 'no iommu found' message for setups
[pve-manager.git] / www / manager6 / qemu / PCIEdit.js
1 Ext.define('PVE.qemu.PCIInputPanel', {
2 extend: 'Proxmox.panel.InputPanel',
3
4 onlineHelp: 'qm_pci_passthrough',
5
6 setVMConfig: function(vmconfig) {
7 var me = this;
8 me.vmconfig = vmconfig;
9
10 var hostpci = me.vmconfig[me.confid] || '';
11
12 var values = PVE.Parser.parsePropertyString(hostpci, 'host');
13 if (values.host) {
14 if (!values.host.match(/^[0-9a-f]{4}:/i)) { // add optional domain
15 values.host = "0000:" + values.host;
16 }
17 if (values.host.length < 11) { // 0000:00:00 format not 0000:00:00.0
18 values.host += ".0";
19 values.multifunction = true;
20 }
21 }
22
23 values['x-vga'] = PVE.Parser.parseBoolean(values['x-vga'], 0);
24 values.pcie = PVE.Parser.parseBoolean(values.pcie, 0);
25 values.rombar = PVE.Parser.parseBoolean(values.rombar, 1);
26
27 me.setValues(values);
28 if (!me.vmconfig.machine || me.vmconfig.machine.indexOf('q35') === -1) {
29 // machine is not set to some variant of q35, so we disable pcie
30 var pcie = me.down('field[name=pcie]');
31 pcie.setDisabled(true);
32 pcie.setBoxLabel(gettext('Q35 only'));
33 }
34
35 if (values.romfile) {
36 me.down('field[name=romfile]').setVisible(true);
37 }
38 },
39
40 onGetValues: function(values) {
41 var me = this;
42 var ret = {};
43 if(!me.confid) {
44 var i;
45 for (i = 0; i < 5; i++) {
46 if (!me.vmconfig['hostpci' + i.toString()]) {
47 me.confid = 'hostpci' + i.toString();
48 break;
49 }
50 }
51 }
52 // remove optional '0000' domain
53 if (values.host.substring(0,5) === '0000:') {
54 values.host = values.host.substring(5);
55 }
56 if (values.multifunction) {
57 // modify host to skip the '.X'
58 values.host = values.host.substring(0, values.host.indexOf('.'));
59 delete values.multifunction;
60 }
61
62 if (values.rombar) {
63 delete values.rombar;
64 } else {
65 values.rombar = 0;
66 }
67
68 if (!values.romfile) {
69 delete values.romfile;
70 }
71
72 ret[me.confid] = PVE.Parser.printPropertyString(values, 'host');
73 return ret;
74 },
75
76 initComponent: function() {
77 var me = this;
78
79 me.nodename = me.pveSelNode.data.node;
80 if (!me.nodename) {
81 throw "no node name specified";
82 }
83
84 me.column1 = [
85 {
86 xtype: 'pvePCISelector',
87 fieldLabel: gettext('Device'),
88 name: 'host',
89 nodename: me.nodename,
90 allowBlank: false,
91 onLoadCallBack: function(store, records, success) {
92 if (!success || !records.length) {
93 return;
94 }
95
96 if (records.every((val) => val.data.iommugroup === -1)) {
97 // no iommu groups
98 var warning = Ext.create('Ext.form.field.Display', {
99 columnWidth: 1,
100 padding: '0 0 10 0',
101 value: 'No IOMMU detected, please activate it.' +
102 'See Documentation for further information.',
103 userCls: 'pmx-hint'
104 });
105 me.items.insert(0, warning);
106 me.updateLayout(); // insert does not trigger that
107 }
108 },
109 listeners: {
110 change: function(pcisel, value) {
111 if (!value) {
112 return;
113 }
114 var pcidev = pcisel.getStore().getById(value);
115 var mdevfield = me.down('field[name=mdev]');
116 mdevfield.setDisabled(!pcidev || !pcidev.data.mdev);
117 if (!pcidev) {
118 return;
119 }
120 var id = pcidev.data.id.substring(0,5); // 00:00
121 var iommu = pcidev.data.iommugroup;
122 // try to find out if there are more devices
123 // in that iommu group
124 if (iommu !== -1) {
125 var count = 0;
126 pcisel.getStore().each(function(record) {
127 if (record.data.iommugroup === iommu &&
128 record.data.id.substring(0,5) !== id)
129 {
130 count++;
131 return false;
132 }
133 });
134 var warning = me.down('#iommuwarning');
135 if (count && !warning) {
136 warning = Ext.create('Ext.form.field.Display', {
137 columnWidth: 1,
138 padding: '0 0 10 0',
139 itemId: 'iommuwarning',
140 value: 'The selected Device is not in a seperate' +
141 'IOMMU group, make sure this is intended.',
142 userCls: 'pmx-hint'
143 });
144 me.items.insert(0, warning);
145 me.updateLayout(); // insert does not trigger that
146 } else if (!count && warning) {
147 me.remove(warning);
148 }
149 }
150 if (pcidev.data.mdev) {
151 mdevfield.setPciID(value);
152 }
153 }
154 }
155 },
156 {
157 xtype: 'proxmoxcheckbox',
158 fieldLabel: gettext('All Functions'),
159 name: 'multifunction'
160 }
161 ];
162
163 me.column2 = [
164 {
165 xtype: 'pveMDevSelector',
166 name: 'mdev',
167 disabled: true,
168 fieldLabel: gettext('MDev Type'),
169 nodename: me.nodename,
170 listeners: {
171 change: function(field, value) {
172 var mf = me.down('field[name=multifunction]');
173 if (!!value) {
174 mf.setValue(false);
175 }
176 mf.setDisabled(!!value);
177 }
178 }
179 },
180 {
181 xtype: 'proxmoxcheckbox',
182 fieldLabel: gettext('Primary GPU'),
183 name: 'x-vga'
184 }
185 ];
186
187 me.advancedColumn1 = [
188 {
189 xtype: 'proxmoxcheckbox',
190 fieldLabel: 'ROM-Bar',
191 name: 'rombar'
192 },
193 {
194 xtype: 'displayfield',
195 submitValue: true,
196 hidden: true,
197 fieldLabel: 'ROM-File',
198 name: 'romfile'
199 }
200 ];
201
202 me.advancedColumn2 = [
203 {
204 xtype: 'proxmoxcheckbox',
205 fieldLabel: 'PCI-Express',
206 name: 'pcie'
207 }
208 ];
209
210 me.callParent();
211 }
212 });
213
214 Ext.define('PVE.qemu.PCIEdit', {
215 extend: 'Proxmox.window.Edit',
216
217 vmconfig: undefined,
218
219 isAdd: true,
220
221 subject: gettext('PCI Device'),
222
223
224 initComponent : function() {
225 var me = this;
226
227 me.isCreate = !me.confid;
228
229 var ipanel = Ext.create('PVE.qemu.PCIInputPanel', {
230 confid: me.confid,
231 pveSelNode: me.pveSelNode
232 });
233
234 Ext.apply(me, {
235 items: [ ipanel ]
236 });
237
238 me.callParent();
239
240 me.load({
241 success: function(response) {
242 ipanel.setVMConfig(response.result.data);
243 }
244 });
245 }
246 });