]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/node/NetworkEdit.js
vlan edit: Forbid blank vlan raw device
[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 listeners: {
250 change: function(f, value) {
251 if (me.isCreate && iface_vtype === 'VlanName') {
252 let vlanidField = me.down('field[name=vlan-id]');
253 let vlanrawdeviceField = me.down('field[name=vlan-raw-device]');
254 if (Proxmox.Utils.VlanInterface_match.test(value)) {
255 vlanidField.setDisabled(true);
256 vlanrawdeviceField.setDisabled(true);
257 } else if (Proxmox.Utils.Vlan_match.test(value)) {
258 vlanidField.setDisabled(true);
259 vlanrawdeviceField.setDisabled(false);
260 } else {
261 vlanidField.setDisabled(false);
262 vlanrawdeviceField.setDisabled(false);
263 }
264 }
265 },
266 },
267 });
268
269 if (me.iftype === 'OVSBond') {
270 column1.push(
271 {
272 xtype: 'bondModeSelector',
273 fieldLabel: gettext('Mode'),
274 name: 'bond_mode',
275 openvswitch: true,
276 value: me.isCreate ? 'active-backup' : undefined,
277 allowBlank: false,
278 },
279 {
280 xtype: 'textfield',
281 fieldLabel: gettext('Slaves'),
282 name: 'ovs_bonds',
283 },
284 );
285 } else {
286 column1.push(
287 {
288 xtype: 'proxmoxtextfield',
289 deleteEmpty: !me.isCreate,
290 fieldLabel: 'IPv4/CIDR',
291 vtype: 'IPCIDRAddress',
292 name: 'cidr',
293 },
294 {
295 xtype: 'proxmoxtextfield',
296 deleteEmpty: !me.isCreate,
297 fieldLabel: gettext('Gateway') + ' (IPv4)',
298 vtype: 'IPAddress',
299 name: 'gateway',
300 },
301 {
302 xtype: 'proxmoxtextfield',
303 deleteEmpty: !me.isCreate,
304 fieldLabel: 'IPv6/CIDR',
305 vtype: 'IP6CIDRAddress',
306 name: 'cidr6',
307 },
308 {
309 xtype: 'proxmoxtextfield',
310 deleteEmpty: !me.isCreate,
311 fieldLabel: gettext('Gateway') + ' (IPv6)',
312 vtype: 'IP6Address',
313 name: 'gateway6',
314 },
315 );
316 }
317 advancedColumn1.push(
318 {
319 xtype: 'proxmoxintegerfield',
320 minValue: 1280,
321 maxValue: 65520,
322 deleteEmpty: !me.isCreate,
323 emptyText: 1500,
324 fieldLabel: 'MTU',
325 name: 'mtu',
326 },
327 );
328
329 Ext.applyIf(me, {
330 url: url,
331 method: method,
332 items: {
333 xtype: 'inputpanel',
334 column1: column1,
335 column2: column2,
336 columnB: columnB,
337 advancedColumn1: advancedColumn1,
338 advancedColumn2: advancedColumn2,
339 },
340 });
341
342 me.callParent();
343
344 if (me.isCreate) {
345 me.down('field[name=iface]').setValue(me.iface_default);
346 } else {
347 me.load({
348 success: function(response, options) {
349 let data = response.result.data;
350 if (data.type !== me.iftype) {
351 let msg = "Got unexpected device type";
352 Ext.Msg.alert(gettext('Error'), msg, function() {
353 me.close();
354 });
355 return;
356 }
357 me.setValues(data);
358 me.isValid(); // trigger validation
359 },
360 });
361 }
362 },
363 });