]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/node/NetworkEdit.js
fix #2703: networkedit: limit custom interface name field to 15 characters.
[proxmox-widget-toolkit.git] / src / node / NetworkEdit.js
1 Ext.define('Proxmox.node.NetworkEdit', {
2 extend: 'Proxmox.window.Edit',
3 alias: ['widget.proxmoxNodeNetworkEdit'],
4
5 initComponent: function() {
6 let me = this;
7
8 if (!me.nodename) {
9 throw "no node name specified";
10 }
11
12 if (!me.iftype) {
13 throw "no network device type specified";
14 }
15
16 me.isCreate = !me.iface;
17
18 let iface_vtype;
19
20 if (me.iftype === 'bridge') {
21 iface_vtype = 'BridgeName';
22 } else if (me.iftype === 'bond') {
23 iface_vtype = 'BondName';
24 } else if (me.iftype === 'eth' && !me.isCreate) {
25 iface_vtype = 'InterfaceName';
26 } else if (me.iftype === 'vlan') {
27 iface_vtype = 'VlanName';
28 } else if (me.iftype === 'OVSBridge') {
29 iface_vtype = 'BridgeName';
30 } else if (me.iftype === 'OVSBond') {
31 iface_vtype = 'BondName';
32 } else if (me.iftype === 'OVSIntPort') {
33 iface_vtype = 'InterfaceName';
34 } else if (me.iftype === 'OVSPort') {
35 iface_vtype = 'InterfaceName';
36 } else {
37 console.log(me.iftype);
38 throw "unknown network device type specified";
39 }
40
41 me.subject = Proxmox.Utils.render_network_iface_type(me.iftype);
42
43 let column1 = [],
44 column2 = [],
45 columnB = [],
46 advancedColumn1 = [],
47 advancedColumn2 = [];
48
49 if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' || me.iftype === 'OVSBond')) {
50 column2.push({
51 xtype: 'proxmoxcheckbox',
52 fieldLabel: gettext('Autostart'),
53 name: 'autostart',
54 uncheckedValue: 0,
55 checked: me.isCreate ? true : undefined,
56 });
57 }
58
59 if (me.iftype === 'bridge') {
60 column2.push({
61 xtype: 'proxmoxcheckbox',
62 fieldLabel: gettext('VLAN aware'),
63 name: 'bridge_vlan_aware',
64 deleteEmpty: !me.isCreate,
65 });
66 column2.push({
67 xtype: 'textfield',
68 fieldLabel: gettext('Bridge ports'),
69 name: 'bridge_ports',
70 });
71 } else if (me.iftype === 'OVSBridge') {
72 column2.push({
73 xtype: 'textfield',
74 fieldLabel: gettext('Bridge ports'),
75 name: 'ovs_ports',
76 });
77 column2.push({
78 xtype: 'textfield',
79 fieldLabel: gettext('OVS options'),
80 name: 'ovs_options',
81 });
82 } else if (me.iftype === 'OVSPort' || me.iftype === 'OVSIntPort') {
83 column2.push({
84 xtype: me.isCreate ? 'PVE.form.BridgeSelector' : 'displayfield',
85 fieldLabel: Proxmox.Utils.render_network_iface_type('OVSBridge'),
86 allowBlank: false,
87 nodename: me.nodename,
88 bridgeType: 'OVSBridge',
89 name: 'ovs_bridge',
90 });
91 column2.push({
92 xtype: 'pveVlanField',
93 deleteEmpty: !me.isCreate,
94 name: 'ovs_tag',
95 value: '',
96 });
97 column2.push({
98 xtype: 'textfield',
99 fieldLabel: gettext('OVS options'),
100 name: 'ovs_options',
101 });
102 } else if (me.iftype === 'vlan') {
103 if (!me.isCreate) {
104 me.disablevlanid = false;
105 me.disablevlanrawdevice = false;
106 me.vlanrawdevicevalue = '';
107 me.vlanidvalue = '';
108
109 if (Proxmox.Utils.VlanInterface_match.test(me.iface)) {
110 me.disablevlanid = true;
111 me.disablevlanrawdevice = true;
112 let arr = Proxmox.Utils.VlanInterface_match.exec(me.iface);
113 me.vlanrawdevicevalue = arr[1];
114 me.vlanidvalue = arr[2];
115 } else if (Proxmox.Utils.Vlan_match.test(me.iface)) {
116 me.disablevlanid = true;
117 let arr = Proxmox.Utils.Vlan_match.exec(me.iface);
118 me.vlanidvalue = arr[1];
119 }
120 } else {
121 me.disablevlanid = true;
122 me.disablevlanrawdevice = true;
123 }
124
125 column2.push({
126 xtype: 'textfield',
127 fieldLabel: gettext('Vlan raw device'),
128 name: 'vlan-raw-device',
129 value: me.vlanrawdevicevalue,
130 disabled: me.disablevlanrawdevice,
131 allowBlank: false,
132 });
133
134 column2.push({
135 xtype: 'pveVlanField',
136 name: 'vlan-id',
137 value: me.vlanidvalue,
138 disabled: me.disablevlanid,
139 });
140
141 columnB.push({
142 xtype: 'label',
143 userCls: 'pmx-hint',
144 text: 'Either add the VLAN number to an existing interface name, or choose your own name and set the VLAN raw device (for the latter ifupdown1 supports vlanXY naming only)',
145 });
146 } else if (me.iftype === 'bond') {
147 column2.push({
148 xtype: 'textfield',
149 fieldLabel: gettext('Slaves'),
150 name: 'slaves',
151 });
152
153 let policySelector = Ext.createWidget('bondPolicySelector', {
154 fieldLabel: gettext('Hash policy'),
155 name: 'bond_xmit_hash_policy',
156 deleteEmpty: !me.isCreate,
157 disabled: true,
158 });
159
160 let primaryfield = Ext.createWidget('textfield', {
161 fieldLabel: 'bond-primary',
162 name: 'bond-primary',
163 value: '',
164 disabled: true,
165 });
166
167 column2.push({
168 xtype: 'bondModeSelector',
169 fieldLabel: gettext('Mode'),
170 name: 'bond_mode',
171 value: me.isCreate ? 'balance-rr' : undefined,
172 listeners: {
173 change: function(f, value) {
174 if (value === 'balance-xor' ||
175 value === '802.3ad') {
176 policySelector.setDisabled(false);
177 primaryfield.setDisabled(true);
178 primaryfield.setValue('');
179 } else if (value === 'active-backup') {
180 primaryfield.setDisabled(false);
181 policySelector.setDisabled(true);
182 policySelector.setValue('');
183 } else {
184 policySelector.setDisabled(true);
185 policySelector.setValue('');
186 primaryfield.setDisabled(true);
187 primaryfield.setValue('');
188 }
189 },
190 },
191 allowBlank: false,
192 });
193
194 column2.push(policySelector);
195 column2.push(primaryfield);
196 } else if (me.iftype === 'OVSBond') {
197 column2.push({
198 xtype: me.isCreate ? 'PVE.form.BridgeSelector' : 'displayfield',
199 fieldLabel: Proxmox.Utils.render_network_iface_type('OVSBridge'),
200 allowBlank: false,
201 nodename: me.nodename,
202 bridgeType: 'OVSBridge',
203 name: 'ovs_bridge',
204 });
205 column2.push({
206 xtype: 'pveVlanField',
207 deleteEmpty: !me.isCreate,
208 name: 'ovs_tag',
209 value: '',
210 });
211 column2.push({
212 xtype: 'textfield',
213 fieldLabel: gettext('OVS options'),
214 name: 'ovs_options',
215 });
216 }
217
218 column2.push({
219 xtype: 'textfield',
220 fieldLabel: gettext('Comment'),
221 allowBlank: true,
222 nodename: me.nodename,
223 name: 'comments',
224 });
225
226 let url;
227 let method;
228
229 if (me.isCreate) {
230 url = "/api2/extjs/nodes/" + me.nodename + "/network";
231 method = 'POST';
232 } else {
233 url = "/api2/extjs/nodes/" + me.nodename + "/network/" + me.iface;
234 method = 'PUT';
235 }
236
237 column1.push({
238 xtype: 'hiddenfield',
239 name: 'type',
240 value: me.iftype,
241 },
242 {
243 xtype: me.isCreate ? 'textfield' : 'displayfield',
244 fieldLabel: gettext('Name'),
245 name: 'iface',
246 value: me.iface,
247 vtype: iface_vtype,
248 allowBlank: false,
249 maxLength: 15,
250 autoEl: {
251 tag: 'div',
252 'data-qtip': gettext('For example, vmbr0.100, vmbr0, vlan0.100, vlan0'),
253 },
254 listeners: {
255 change: function(f, value) {
256 if (me.isCreate && iface_vtype === 'VlanName') {
257 let vlanidField = me.down('field[name=vlan-id]');
258 let vlanrawdeviceField = me.down('field[name=vlan-raw-device]');
259 if (Proxmox.Utils.VlanInterface_match.test(value)) {
260 vlanidField.setDisabled(true);
261 vlanrawdeviceField.setDisabled(true);
262 // User defined those values in the `iface` (Name)
263 // field. Match them (instead of leaving the
264 // previous value) to make clear what is submitted
265 // and how the fields `iface`, `vlan-id` and
266 // `vlan-raw-device` are connected
267 vlanidField.setValue(
268 value.match(Proxmox.Utils.VlanInterface_match)[2],
269 );
270 vlanrawdeviceField.setValue(
271 value.match(Proxmox.Utils.VlanInterface_match)[1],
272 );
273 } else if (Proxmox.Utils.Vlan_match.test(value)) {
274 vlanidField.setDisabled(true);
275 vlanidField.setValue(
276 value.match(Proxmox.Utils.Vlan_match)[1],
277 );
278 vlanrawdeviceField.setDisabled(false);
279 } else {
280 vlanidField.setDisabled(false);
281 vlanrawdeviceField.setDisabled(false);
282 }
283 }
284 },
285 },
286 });
287
288 if (me.iftype === 'OVSBond') {
289 column1.push(
290 {
291 xtype: 'bondModeSelector',
292 fieldLabel: gettext('Mode'),
293 name: 'bond_mode',
294 openvswitch: true,
295 value: me.isCreate ? 'active-backup' : undefined,
296 allowBlank: false,
297 },
298 {
299 xtype: 'textfield',
300 fieldLabel: gettext('Slaves'),
301 name: 'ovs_bonds',
302 },
303 );
304 } else {
305 column1.push(
306 {
307 xtype: 'proxmoxtextfield',
308 deleteEmpty: !me.isCreate,
309 fieldLabel: 'IPv4/CIDR',
310 vtype: 'IPCIDRAddress',
311 name: 'cidr',
312 },
313 {
314 xtype: 'proxmoxtextfield',
315 deleteEmpty: !me.isCreate,
316 fieldLabel: gettext('Gateway') + ' (IPv4)',
317 vtype: 'IPAddress',
318 name: 'gateway',
319 },
320 {
321 xtype: 'proxmoxtextfield',
322 deleteEmpty: !me.isCreate,
323 fieldLabel: 'IPv6/CIDR',
324 vtype: 'IP6CIDRAddress',
325 name: 'cidr6',
326 },
327 {
328 xtype: 'proxmoxtextfield',
329 deleteEmpty: !me.isCreate,
330 fieldLabel: gettext('Gateway') + ' (IPv6)',
331 vtype: 'IP6Address',
332 name: 'gateway6',
333 },
334 );
335 }
336 advancedColumn1.push(
337 {
338 xtype: 'proxmoxintegerfield',
339 minValue: 1280,
340 maxValue: 65520,
341 deleteEmpty: !me.isCreate,
342 emptyText: 1500,
343 fieldLabel: 'MTU',
344 name: 'mtu',
345 },
346 );
347
348 Ext.applyIf(me, {
349 url: url,
350 method: method,
351 items: {
352 xtype: 'inputpanel',
353 column1: column1,
354 column2: column2,
355 columnB: columnB,
356 advancedColumn1: advancedColumn1,
357 advancedColumn2: advancedColumn2,
358 },
359 });
360
361 me.callParent();
362
363 if (me.isCreate) {
364 me.down('field[name=iface]').setValue(me.iface_default);
365 } else {
366 me.load({
367 success: function(response, options) {
368 let data = response.result.data;
369 if (data.type !== me.iftype) {
370 let msg = "Got unexpected device type";
371 Ext.Msg.alert(gettext('Error'), msg, function() {
372 me.close();
373 });
374 return;
375 }
376 me.setValues(data);
377 me.isValid(); // trigger validation
378 },
379 });
380 }
381 },
382 });