]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/qemu/PCIEdit.js
update shipped appliance info index
[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_vm_config',
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 let me = this;
42 if (!me.confid) {
43 for (let i = 0; i < PVE.Utils.hardware_counts.hostpci; i++) {
44 if (!me.vmconfig['hostpci' + i.toString()]) {
45 me.confid = 'hostpci' + i.toString();
46 break;
47 }
48 }
49 // FIXME: what if no confid was found??
50 }
51 values.host.replace(/^0000:/, ''); // remove optional '0000' domain
52
53 if (values.multifunction) {
54 values.host = values.host.substring(0, values.host.indexOf('.')); // skip the '.X'
55 delete values.multifunction;
56 }
57
58 if (values.rombar) {
59 delete values.rombar;
60 } else {
61 values.rombar = 0;
62 }
63
64 if (!values.romfile) {
65 delete values.romfile;
66 }
67
68 let ret = {};
69 ret[me.confid] = PVE.Parser.printPropertyString(values, 'host');
70 return ret;
71 },
72
73 initComponent: function() {
74 let 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 if (records.every((val) => val.data.iommugroup === -1)) { // no IOMMU groups
93 let warning = Ext.create('Ext.form.field.Display', {
94 columnWidth: 1,
95 padding: '0 0 10 0',
96 value: 'No IOMMU detected, please activate it.' +
97 'See Documentation for further information.',
98 userCls: 'pmx-hint',
99 });
100 me.items.insert(0, warning);
101 me.updateLayout(); // insert does not trigger that
102 }
103 },
104 listeners: {
105 change: function(pcisel, value) {
106 if (!value) {
107 return;
108 }
109 let pciDev = pcisel.getStore().getById(value);
110 let mdevfield = me.down('field[name=mdev]');
111 mdevfield.setDisabled(!pciDev || !pciDev.data.mdev);
112 if (!pciDev) {
113 return;
114 }
115 if (pciDev.data.mdev) {
116 mdevfield.setPciID(value);
117 }
118 let iommu = pciDev.data.iommugroup;
119 if (iommu === -1) {
120 return;
121 }
122 // try to find out if there are more devices in that iommu group
123 let id = pciDev.data.id.substring(0, 5); // 00:00
124 let count = 0;
125 pcisel.getStore().each(({ data }) => {
126 if (data.iommugroup === iommu && data.id.substring(0, 5) !== id) {
127 count++;
128 return false;
129 }
130 return true;
131 });
132 let 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 IOMMU group, make sure this is intended.',
139 userCls: 'pmx-hint',
140 });
141 me.items.insert(0, warning);
142 me.updateLayout(); // insert does not trigger that
143 } else if (!count && warning) {
144 me.remove(warning);
145 }
146 },
147 },
148 },
149 {
150 xtype: 'proxmoxcheckbox',
151 fieldLabel: gettext('All Functions'),
152 name: 'multifunction',
153 },
154 ];
155
156 me.column2 = [
157 {
158 xtype: 'pveMDevSelector',
159 name: 'mdev',
160 disabled: true,
161 fieldLabel: gettext('MDev Type'),
162 nodename: me.nodename,
163 listeners: {
164 change: function(field, value) {
165 let multiFunction = me.down('field[name=multifunction]');
166 if (value) {
167 multiFunction.setValue(false);
168 }
169 multiFunction.setDisabled(!!value);
170 },
171 },
172 },
173 {
174 xtype: 'proxmoxcheckbox',
175 fieldLabel: gettext('Primary GPU'),
176 name: 'x-vga',
177 },
178 ];
179
180 me.advancedColumn1 = [
181 {
182 xtype: 'proxmoxcheckbox',
183 fieldLabel: 'ROM-Bar',
184 name: 'rombar',
185 },
186 {
187 xtype: 'displayfield',
188 submitValue: true,
189 hidden: true,
190 fieldLabel: 'ROM-File',
191 name: 'romfile',
192 },
193 {
194 xtype: 'textfield',
195 name: 'vendor-id',
196 fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Vendor')),
197 emptyText: gettext('From Device'),
198 vtype: 'PciId',
199 allowBlank: true,
200 submitEmpty: false,
201 },
202 {
203 xtype: 'textfield',
204 name: 'device-id',
205 fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Device')),
206 emptyText: gettext('From Device'),
207 vtype: 'PciId',
208 allowBlank: true,
209 submitEmpty: false,
210 },
211 ];
212
213 me.advancedColumn2 = [
214 {
215 xtype: 'proxmoxcheckbox',
216 fieldLabel: 'PCI-Express',
217 name: 'pcie',
218 },
219 {
220 xtype: 'textfield',
221 name: 'sub-vendor-id',
222 fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Sub-Vendor')),
223 emptyText: gettext('From Device'),
224 vtype: 'PciId',
225 allowBlank: true,
226 submitEmpty: false,
227 },
228 {
229 xtype: 'textfield',
230 name: 'sub-device-id',
231 fieldLabel: Ext.String.format(gettext('{0} ID'), gettext('Sub-Device')),
232 emptyText: gettext('From Device'),
233 vtype: 'PciId',
234 allowBlank: true,
235 submitEmpty: false,
236 },
237 ];
238
239 me.callParent();
240 },
241 });
242
243 Ext.define('PVE.qemu.PCIEdit', {
244 extend: 'Proxmox.window.Edit',
245
246 subject: gettext('PCI Device'),
247
248 vmconfig: undefined,
249 isAdd: true,
250
251 initComponent: function() {
252 let me = this;
253
254 me.isCreate = !me.confid;
255
256 let ipanel = Ext.create('PVE.qemu.PCIInputPanel', {
257 confid: me.confid,
258 pveSelNode: me.pveSelNode,
259 });
260
261 Ext.apply(me, {
262 items: [ipanel],
263 });
264
265 me.callParent();
266
267 me.load({
268 success: ({ result }) => ipanel.setVMConfig(result.data),
269 });
270 },
271 });