]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/node/NetworkEdit.js
af798d503149a231ffc40bd8fe817831862b04f9
[pve-manager.git] / www / manager6 / node / NetworkEdit.js
1 Ext.define('PVE.node.NetworkEdit', {
2 extend: 'PVE.window.Edit',
3 alias: ['widget.pveNodeNetworkEdit'],
4
5 initComponent : function() {
6 var me = this;
7
8 var nodename = me.pveSelNode.data.node;
9 if (!nodename) {
10 throw "no node name specified";
11 }
12
13 if (!me.iftype) {
14 throw "no network device type specified";
15 }
16
17 me.create = !me.iface;
18
19 var iface_vtype;
20
21 if (me.iftype === 'bridge') {
22 iface_vtype = 'BridgeName';
23 } else if (me.iftype === 'bond') {
24 iface_vtype = 'BondName';
25 } else if (me.iftype === 'eth' && !me.create) {
26 iface_vtype = 'InterfaceName';
27 } else if (me.iftype === 'vlan' && !me.create) {
28 iface_vtype = 'InterfaceName';
29 } else if (me.iftype === 'OVSBridge') {
30 iface_vtype = 'BridgeName';
31 } else if (me.iftype === 'OVSBond') {
32 iface_vtype = 'BondName';
33 } else if (me.iftype === 'OVSIntPort') {
34 iface_vtype = 'InterfaceName';
35 } else if (me.iftype === 'OVSPort') {
36 iface_vtype = 'InterfaceName';
37 } else {
38 console.log(me.iftype);
39 throw "unknown network device type specified";
40 }
41
42 me.subject = PVE.Utils.render_network_iface_type(me.iftype);
43
44 var column2 = [];
45
46 if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' ||
47 me.iftype === 'OVSBond')) {
48 column2.push({
49 xtype: 'pvecheckbox',
50 fieldLabel: gettext('Autostart'),
51 name: 'autostart',
52 uncheckedValue: 0,
53 checked: me.create ? true : undefined
54 });
55 }
56
57 if (me.iftype === 'bridge') {
58 column2.push({
59 xtype: 'pvecheckbox',
60 fieldLabel: gettext('Vlan Aware'),
61 name: 'bridge_vlan_aware',
62 deleteEmpty: !me.create,
63 });
64 column2.push({
65 xtype: 'textfield',
66 fieldLabel: gettext('Bridge ports'),
67 name: 'bridge_ports'
68 });
69 } else if (me.iftype === 'OVSBridge') {
70 column2.push({
71 xtype: 'textfield',
72 fieldLabel: gettext('Bridge ports'),
73 name: 'ovs_ports'
74 });
75 column2.push({
76 xtype: 'textfield',
77 fieldLabel: gettext('OVS options'),
78 name: 'ovs_options'
79 });
80 } else if (me.iftype === 'OVSPort' || me.iftype === 'OVSIntPort') {
81 column2.push({
82 xtype: me.create ? 'PVE.form.BridgeSelector' : 'displayfield',
83 height: 22, // hack: set same height as text fields
84 fieldLabel: PVE.Utils.render_network_iface_type('OVSBridge'),
85 allowBlank: false,
86 nodename: nodename,
87 bridgeType: 'OVSBridge',
88 name: 'ovs_bridge'
89 });
90 column2.push({
91 xtype: 'pveVlanField',
92 deleteEmpty: !me.create,
93 name: 'ovs_tag',
94 value: ''
95 });
96 column2.push({
97 xtype: 'textfield',
98 fieldLabel: gettext('OVS options'),
99 name: 'ovs_options'
100 });
101 } else if (me.iftype === 'bond') {
102 column2.push({
103 xtype: 'textfield',
104 fieldLabel: gettext('Slaves'),
105 name: 'slaves'
106 });
107
108 var policySelector = Ext.createWidget('bondPolicySelector', {
109 fieldLabel: gettext('Hash policy'),
110 name: 'bond_xmit_hash_policy',
111 deleteEmpty: !me.create,
112 disabled: true
113 });
114
115 column2.push({
116 xtype: 'bondModeSelector',
117 fieldLabel: gettext('Mode'),
118 name: 'bond_mode',
119 value: me.create ? 'balance-rr' : undefined,
120 listeners: {
121 change: function(f, value) {
122 if (value === 'balance-xor' ||
123 value === '802.3ad') {
124 policySelector.setDisabled(false);
125 } else {
126 policySelector.setDisabled(true);
127 policySelector.setValue('');
128 }
129 }
130 },
131 allowBlank: false
132 });
133
134 column2.push(policySelector);
135
136 } else if (me.iftype === 'OVSBond') {
137 column2.push({
138 xtype: me.create ? 'PVE.form.BridgeSelector' : 'displayfield',
139 height: 22, // hack: set same height as text fields
140 fieldLabel: PVE.Utils.render_network_iface_type('OVSBridge'),
141 allowBlank: false,
142 nodename: nodename,
143 bridgeType: 'OVSBridge',
144 name: 'ovs_bridge'
145 });
146 column2.push({
147 xtype: 'pveVlanField',
148 deleteEmpty: !me.create,
149 name: 'ovs_tag',
150 value: ''
151 });
152 column2.push({
153 xtype: 'textfield',
154 fieldLabel: gettext('OVS options'),
155 name: 'ovs_options'
156 });
157 }
158
159 var url;
160 var method;
161
162 if (me.create) {
163 url = "/api2/extjs/nodes/" + nodename + "/network";
164 method = 'POST';
165 } else {
166 url = "/api2/extjs/nodes/" + nodename + "/network/" + me.iface;
167 method = 'PUT';
168 }
169
170 var column1 = [
171 {
172 xtype: 'hiddenfield',
173 name: 'type',
174 value: me.iftype
175 },
176 {
177 xtype: me.create ? 'textfield' : 'displayfield',
178 fieldLabel: gettext('Name'),
179 height: 22, // hack: set same height as text fields
180 name: 'iface',
181 value: me.iface,
182 vtype: iface_vtype,
183 allowBlank: false
184 }
185 ];
186
187 if (me.iftype === 'OVSBond') {
188 column1.push(
189 {
190 xtype: 'bondModeSelector',
191 fieldLabel: gettext('Mode'),
192 name: 'bond_mode',
193 openvswitch: true,
194 value: me.create ? 'active-backup' : undefined,
195 allowBlank: false
196 },
197 {
198 xtype: 'textfield',
199 fieldLabel: gettext('Slaves'),
200 name: 'ovs_bonds'
201 }
202 );
203 } else {
204
205 column1.push(
206 {
207 xtype: 'pvetextfield',
208 deleteEmpty: !me.create,
209 fieldLabel: gettext('IP address'),
210 vtype: 'IPAddress',
211 name: 'address'
212 },
213 {
214 xtype: 'pvetextfield',
215 deleteEmpty: !me.create,
216 fieldLabel: gettext('Subnet mask'),
217 vtype: 'IPAddress',
218 name: 'netmask',
219 validator: function(value) {
220 /*jslint confusion: true */
221 if (!me.items) {
222 return true;
223 }
224 var address = me.down('field[name=address]').getValue();
225 if (value !== '') {
226 if (address === '') {
227 return "Subnet mask requires option 'IP address'";
228 }
229 } else {
230 if (address !== '') {
231 return "Option 'IP address' requires a subnet mask";
232 }
233 }
234
235 return true;
236 }
237 },
238 {
239 xtype: 'pvetextfield',
240 deleteEmpty: !me.create,
241 fieldLabel: gettext('Gateway'),
242 vtype: 'IPAddress',
243 name: 'gateway'
244 },
245 {
246 xtype: 'pvetextfield',
247 deleteEmpty: !me.create,
248 fieldLabel: gettext('IPv6 address'),
249 vtype: 'IP6Address',
250 name: 'address6'
251 },
252 {
253 xtype: 'pvetextfield',
254 deleteEmpty: !me.create,
255 fieldLabel: gettext('Prefix length'),
256 vtype: 'IP6PrefixLength',
257 name: 'netmask6',
258 value: '',
259 allowBlank: true,
260 validator: function(value) {
261 /*jslint confusion: true */
262 if (!me.items) {
263 return true;
264 }
265 var address = me.down('field[name=address6]').getValue();
266 if (value !== '') {
267 if (address === '') {
268 return "IPv6 prefix length requires option 'IPv6 address'";
269 }
270 } else {
271 if (address !== '') {
272 return "Option 'IPv6 address' requires an IPv6 prefix length";
273 }
274 }
275
276 return true;
277 }
278 },
279 {
280 xtype: 'pvetextfield',
281 deleteEmpty: !me.create,
282 fieldLabel: gettext('Gateway'),
283 vtype: 'IP6Address',
284 name: 'gateway6'
285 }
286 );
287 }
288
289 Ext.applyIf(me, {
290 url: url,
291 method: method,
292 items: {
293 xtype: 'inputpanel',
294 column1: column1,
295 column2: column2
296 }
297 });
298
299 me.callParent();
300
301 if (me.create) {
302 me.down('field[name=iface]').setValue(me.iface_default);
303 } else {
304 me.load({
305 success: function(response, options) {
306 var data = response.result.data;
307 if (data.type !== me.iftype) {
308 var msg = "Got unexpected device type";
309 Ext.Msg.alert(gettext('Error'), msg, function() {
310 me.close();
311 });
312 return;
313 }
314 me.setValues(data);
315 me.isValid(); // trigger validation
316 }
317 });
318 }
319 }
320 });