]> git.proxmox.com Git - pve-manager.git/blob - www/manager/node/NetworkEdit.js
add GUI for openvswitch network
[pve-manager.git] / www / manager / 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 === 'OVSBridge') {
28 iface_vtype = 'BridgeName';
29 } else if (me.iftype === 'OVSBond') {
30 iface_vtype = 'BondName';
31 } else if (me.iftype === 'OVSIntPort') {
32 iface_vtype = 'InterfaceName';
33 } else if (me.iftype === 'OVSPort') {
34 iface_vtype = 'InterfaceName';
35 } else {
36 console.log(me.iftype);
37 throw "unknown network device type specified";
38 }
39
40 me.subject = PVE.Utils.render_network_iface_type(me.iftype);
41
42 var column2 = [];
43
44 if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' ||
45 me.iftype === 'OVSBond')) {
46 column2.push({
47 xtype: 'pvecheckbox',
48 fieldLabel: gettext('Autostart'),
49 name: 'autostart',
50 uncheckedValue: 0,
51 checked: me.create ? true : undefined
52 });
53 }
54
55 if (me.iftype === 'bridge') {
56 column2.push({
57 xtype: 'textfield',
58 fieldLabel: gettext('Bridge ports'),
59 name: 'bridge_ports'
60 });
61 } else if (me.iftype === 'OVSBridge') {
62 column2.push({
63 xtype: 'textfield',
64 fieldLabel: gettext('Bridge ports'),
65 name: 'ovs_ports'
66 });
67 column2.push({
68 xtype: 'textfield',
69 fieldLabel: gettext('OVS options'),
70 name: 'ovs_options'
71 });
72 } else if (me.iftype === 'OVSPort' || me.iftype === 'OVSIntPort') {
73 column2.push({
74 xtype: me.create ? 'PVE.form.BridgeSelector' : 'displayfield',
75 height: 22, // hack: set same height as text fields
76 fieldLabel: PVE.Utils.render_network_iface_type('OVSBridge'),
77 allowBlank: false,
78 nodename: nodename,
79 bridgeType: 'OVSBridge',
80 name: 'ovs_bridge'
81 });
82 column2.push({
83 xtype: 'textfield',
84 fieldLabel: gettext('OVS options'),
85 name: 'ovs_options'
86 });
87 } else if (me.iftype === 'bond') {
88 column2.push({
89 xtype: 'textfield',
90 fieldLabel: gettext('Slaves'),
91 name: 'slaves'
92 });
93 column2.push({
94 xtype: 'bondModeSelector',
95 fieldLabel: gettext('Mode'),
96 name: 'bond_mode',
97 value: me.create ? 'balance-rr' : undefined,
98 allowBlank: false
99 });
100 } else if (me.iftype === 'OVSBond') {
101 column2.push({
102 xtype: me.create ? 'PVE.form.BridgeSelector' : 'displayfield',
103 height: 22, // hack: set same height as text fields
104 fieldLabel: PVE.Utils.render_network_iface_type('OVSBridge'),
105 allowBlank: false,
106 nodename: nodename,
107 bridgeType: 'OVSBridge',
108 name: 'ovs_bridge'
109 });
110 column2.push({
111 xtype: 'textfield',
112 fieldLabel: gettext('OVS options'),
113 name: 'ovs_options'
114 });
115 }
116
117 var url;
118 var method;
119
120 if (me.create) {
121 url = "/api2/extjs/nodes/" + nodename + "/network";
122 method = 'POST';
123 } else {
124 url = "/api2/extjs/nodes/" + nodename + "/network/" + me.iface;
125 method = 'PUT';
126 }
127
128 var column1 = [
129 {
130 xtype: 'hiddenfield',
131 name: 'type',
132 value: me.iftype
133 },
134 {
135 xtype: me.create ? 'textfield' : 'displayfield',
136 fieldLabel: gettext('Name'),
137 height: 22, // hack: set same height as text fields
138 name: 'iface',
139 value: me.iface,
140 vtype: iface_vtype,
141 allowBlank: false
142 }
143 ];
144
145 if (me.iftype === 'OVSPort') {
146 // nothing to edit
147 } else if (me.iftype === 'OVSBond') {
148 column1.push([
149 {
150 xtype: 'textfield',
151 fieldLabel: gettext('Slaves'),
152 name: 'ovs_bonds'
153 },
154 {
155 xtype: 'bondModeSelector',
156 fieldLabel: gettext('Mode'),
157 name: 'bond_mode',
158 openvswitch: true,
159 value: me.create ? 'active-backup' : undefined,
160 allowBlank: false
161 }
162 ]);
163 } else {
164
165 column1.push([
166 {
167 xtype: 'pvetextfield',
168 deleteEmpty: !me.create,
169 fieldLabel: gettext('IP address'),
170 vtype: 'IPAddress',
171 name: 'address'
172 },
173 {
174 xtype: 'pvetextfield',
175 deleteEmpty: !me.create,
176 fieldLabel: gettext('Subnet mask'),
177 vtype: 'IPAddress',
178 name: 'netmask',
179 validator: function(value) {
180 /*jslint confusion: true */
181 if (!me.items) {
182 return true;
183 }
184 var address = me.down('field[name=address]').getValue();
185 if (value !== '') {
186 if (address === '') {
187 return "Subnet mask requires option 'IP address'";
188 }
189 } else {
190 if (address !== '') {
191 return "Option 'IP address' requires a subnet mask";
192 }
193 }
194
195 return true;
196 }
197 },
198 {
199 xtype: 'pvetextfield',
200 deleteEmpty: !me.create,
201 fieldLabel: gettext('Gateway'),
202 vtype: 'IPAddress',
203 name: 'gateway'
204 }
205 ]);
206 }
207
208 Ext.applyIf(me, {
209 url: url,
210 method: method,
211 items: {
212 xtype: 'inputpanel',
213 column1: column1,
214 column2: column2
215 }
216 });
217
218 me.callParent();
219
220 if (me.create) {
221 me.down('field[name=iface]').setValue(me.iface_default);
222 } else {
223 me.load({
224 success: function(response, options) {
225 var data = response.result.data;
226 if (data.type !== me.iftype) {
227 var msg = "Got unexpected device type";
228 Ext.Msg.alert(gettext('Error'), msg, function() {
229 me.close();
230 });
231 return;
232 }
233 me.setValues(data);
234 me.isValid(); // trigger validation
235 }
236 });
237 }
238 }
239 });