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