]>
Commit | Line | Data |
---|---|---|
2ffe0f32 DC |
1 | Ext.define('PVE.window.PCIMapEditWindow', { |
2 | extend: 'Proxmox.window.Edit', | |
3 | ||
4 | mixins: ['Proxmox.Mixin.CBind'], | |
5 | ||
6 | width: 800, | |
7 | ||
8 | subject: gettext('PCI mapping'), | |
9 | ||
10 | onlineHelp: 'resource_mapping', | |
11 | ||
12 | method: 'POST', | |
13 | ||
14 | cbindData: function(initialConfig) { | |
15 | let me = this; | |
bd712824 DC |
16 | me.isCreate = !me.name || !me.nodename; |
17 | me.method = me.name ? 'PUT' : 'POST'; | |
2ffe0f32 DC |
18 | return { |
19 | name: me.name, | |
20 | nodename: me.nodename, | |
21 | }; | |
22 | }, | |
23 | ||
24 | submitUrl: function(_url, data) { | |
25 | let me = this; | |
bd712824 | 26 | let name = me.method === 'PUT' ? me.name : ''; |
2ffe0f32 DC |
27 | return `/cluster/mapping/pci/${name}`; |
28 | }, | |
29 | ||
30 | controller: { | |
31 | xclass: 'Ext.app.ViewController', | |
32 | ||
33 | onGetValues: function(values) { | |
34 | let me = this; | |
35 | let view = me.getView(); | |
36 | if (view.method === "POST") { | |
37 | delete me.digest; | |
38 | } | |
39 | ||
40 | if (values.iommugroup === -1) { | |
41 | delete values.iommugroup; | |
42 | } | |
43 | ||
44 | let nodename = values.node ?? view.nodename; | |
45 | delete values.node; | |
46 | if (me.originalMap) { | |
47 | let otherMaps = PVE.Parser | |
48 | .filterPropertyStringList(me.originalMap, (e) => e.node !== nodename); | |
49 | if (otherMaps.length) { | |
50 | values.map = values.map.concat(otherMaps); | |
51 | } | |
52 | } | |
53 | ||
54 | return values; | |
55 | }, | |
56 | ||
57 | onSetValues: function(values) { | |
58 | let me = this; | |
59 | let view = me.getView(); | |
60 | me.originalMap = [...values.map]; | |
61 | values.map = PVE.Parser.filterPropertyStringList(values.map, (e) => e.node === view.nodename); | |
62 | return values; | |
63 | }, | |
64 | ||
65 | checkIommu: function(store, records, success) { | |
66 | let me = this; | |
67 | if (!success || !records.length) { | |
68 | return; | |
69 | } | |
70 | me.lookup('iommu_warning').setVisible( | |
71 | records.every((val) => val.data.iommugroup === -1), | |
72 | ); | |
e633ac0f DC |
73 | |
74 | let value = me.lookup('pciselector').getValue(); | |
75 | me.checkIsolated(value); | |
76 | }, | |
77 | ||
78 | checkIsolated: function(value) { | |
79 | let me = this; | |
80 | ||
81 | let store = me.lookup('pciselector').getStore(); | |
82 | ||
83 | let isIsolated = function(entry) { | |
84 | let isolated = true; | |
85 | let parsed = PVE.Parser.parsePropertyString(entry); | |
86 | parsed.iommugroup = parseInt(parsed.iommugroup, 10); | |
87 | if (!parsed.iommugroup) { | |
88 | return isolated; | |
89 | } | |
90 | store.each(({ data }) => { | |
91 | let isSubDevice = data.id.startsWith(parsed.path); | |
92 | if (data.iommugroup === parsed.iommugroup && data.id !== parsed.path && !isSubDevice) { | |
93 | isolated = false; | |
94 | return false; | |
95 | } | |
96 | return true; | |
97 | }); | |
98 | return isolated; | |
99 | }; | |
100 | ||
101 | let showWarning = false; | |
102 | if (Ext.isArray(value)) { | |
103 | for (const entry of value) { | |
104 | if (!isIsolated(entry)) { | |
105 | showWarning = true; | |
106 | break; | |
107 | } | |
108 | } | |
109 | } else { | |
110 | showWarning = isIsolated(value); | |
111 | } | |
112 | me.lookup('group_warning').setVisible(showWarning); | |
2ffe0f32 DC |
113 | }, |
114 | ||
115 | mdevChange: function(mdevField, value) { | |
116 | this.lookup('pciselector').setMdev(value); | |
117 | }, | |
118 | ||
119 | nodeChange: function(_field, value) { | |
120 | this.lookup('pciselector').setNodename(value); | |
121 | }, | |
122 | ||
123 | pciChange: function(_field, value) { | |
124 | let me = this; | |
125 | me.lookup('multiple_warning').setVisible(Ext.isArray(value) && value.length > 1); | |
e633ac0f | 126 | me.checkIsolated(value); |
2ffe0f32 DC |
127 | }, |
128 | ||
129 | control: { | |
130 | 'field[name=mdev]': { | |
131 | change: 'mdevChange', | |
132 | }, | |
133 | 'pveNodeSelector': { | |
134 | change: 'nodeChange', | |
135 | }, | |
136 | 'pveMultiPCISelector': { | |
137 | change: 'pciChange', | |
138 | }, | |
139 | }, | |
140 | }, | |
141 | ||
142 | items: [ | |
143 | { | |
144 | xtype: 'inputpanel', | |
145 | onGetValues: function(values) { | |
146 | return this.up('window').getController().onGetValues(values); | |
147 | }, | |
148 | ||
149 | onSetValues: function(values) { | |
150 | return this.up('window').getController().onSetValues(values); | |
151 | }, | |
152 | ||
153 | columnT: [ | |
154 | { | |
155 | xtype: 'displayfield', | |
156 | reference: 'iommu_warning', | |
157 | hidden: true, | |
158 | columnWidth: 1, | |
159 | padding: '0 0 10 0', | |
160 | value: 'No IOMMU detected, please activate it.' + | |
161 | 'See Documentation for further information.', | |
162 | userCls: 'pmx-hint', | |
163 | }, | |
164 | { | |
165 | xtype: 'displayfield', | |
166 | reference: 'multiple_warning', | |
167 | hidden: true, | |
168 | columnWidth: 1, | |
169 | padding: '0 0 10 0', | |
170 | value: 'When multiple devices are selected, the first free one will be chosen' + | |
171 | ' on guest start.', | |
172 | userCls: 'pmx-hint', | |
173 | }, | |
174 | { | |
175 | xtype: 'displayfield', | |
176 | reference: 'group_warning', | |
177 | hidden: true, | |
178 | columnWidth: 1, | |
179 | padding: '0 0 10 0', | |
180 | itemId: 'iommuwarning', | |
181 | value: 'The selected Device is not in a seperate IOMMU group, make sure this is intended.', | |
182 | userCls: 'pmx-hint', | |
183 | }, | |
184 | ], | |
185 | ||
186 | column1: [ | |
187 | { | |
188 | xtype: 'pmxDisplayEditField', | |
189 | fieldLabel: gettext('Name'), | |
190 | labelWidth: 120, | |
191 | cbind: { | |
192 | editable: '{!name}', | |
193 | value: '{name}', | |
194 | submitValue: '{isCreate}', | |
195 | }, | |
196 | name: 'id', | |
197 | allowBlank: false, | |
198 | }, | |
2ffe0f32 DC |
199 | { |
200 | xtype: 'pmxDisplayEditField', | |
bd712824 | 201 | fieldLabel: gettext('Mapping on Node'), |
2ffe0f32 DC |
202 | labelWidth: 120, |
203 | name: 'node', | |
204 | editConfig: { | |
205 | xtype: 'pveNodeSelector', | |
206 | }, | |
207 | cbind: { | |
208 | editable: '{!nodename}', | |
209 | value: '{nodename}', | |
210 | }, | |
211 | allowBlank: false, | |
212 | }, | |
213 | ], | |
214 | ||
bd712824 DC |
215 | column2: [ |
216 | { | |
217 | // as spacer | |
218 | xtype: 'displayfield', | |
219 | }, | |
220 | { | |
221 | xtype: 'proxmoxcheckbox', | |
222 | fieldLabel: gettext('Mediated Devices'), | |
223 | labelWidth: 120, | |
224 | reference: 'mdev', | |
225 | name: 'mdev', | |
226 | cbind: { | |
227 | deleteEmpty: '{!isCreate}', | |
228 | }, | |
229 | }, | |
230 | ], | |
231 | ||
2ffe0f32 DC |
232 | columnB: [ |
233 | { | |
234 | xtype: 'pveMultiPCISelector', | |
235 | fieldLabel: gettext('Device'), | |
236 | labelWidth: 120, | |
237 | height: 300, | |
238 | reference: 'pciselector', | |
239 | name: 'map', | |
240 | cbind: { | |
241 | nodename: '{nodename}', | |
242 | }, | |
243 | allowBlank: false, | |
244 | onLoadCallBack: 'checkIommu', | |
245 | margin: '0 0 10 0', | |
246 | }, | |
247 | { | |
248 | xtype: 'proxmoxtextfield', | |
249 | fieldLabel: gettext('Comment'), | |
250 | labelWidth: 120, | |
251 | submitValue: true, | |
252 | name: 'description', | |
253 | cbind: { | |
254 | deleteEmpty: '{!isCreate}', | |
255 | }, | |
256 | }, | |
257 | ], | |
258 | }, | |
259 | ], | |
260 | }); |