]> git.proxmox.com Git - proxmox-widget-toolkit.git/blame - node/NetworkView.js
node/net: move MTU to advanced section
[proxmox-widget-toolkit.git] / node / NetworkView.js
CommitLineData
a58001dd
DM
1Ext.define('proxmox-networks', {
2 extend: 'Ext.data.Model',
3 fields: [
4 'iface', 'type', 'active', 'autostart',
5 'bridge_ports', 'slaves',
6 'address', 'netmask', 'gateway',
7 'address6', 'netmask6', 'gateway6',
d0c2b878 8 'cidr', 'cidr6',
a58001dd
DM
9 'comments'
10 ],
11 idProperty: 'iface'
12});
13
14Ext.define('Proxmox.node.NetworkView', {
15 extend: 'Ext.panel.Panel',
16
17 alias: ['widget.proxmoxNodeNetworkView'],
18
7c0e4c25
DC
19 // defines what types of network devices we want to create
20 // order is always the same
8aefd47c 21 types: ['bridge', 'bond', 'vlan', 'ovs'],
7c0e4c25 22
21cd6c09
DC
23 showApplyBtn: false,
24
a58001dd
DM
25 initComponent : function() {
26 var me = this;
27
28 if (!me.nodename) {
29 throw "no node name specified";
30 }
31
32 var baseUrl = '/nodes/' + me.nodename + '/network';
33
34 var store = Ext.create('Ext.data.Store', {
35 model: 'proxmox-networks',
36 proxy: {
37 type: 'proxmox',
38 url: '/api2/json' + baseUrl
39 },
40 sorters: [
41 {
42 property : 'iface',
43 direction: 'ASC'
44 }
45 ]
46 });
47
48 var reload = function() {
49 var changeitem = me.down('#changes');
21cd6c09 50 var apply_btn = me.down('#apply');
03e93db5 51 var revert_btn = me.down('#revert');
a58001dd
DM
52 Proxmox.Utils.API2Request({
53 url: baseUrl,
54 failure: function(response, opts) {
a58001dd 55 store.loadData({});
b81cf173
DM
56 Proxmox.Utils.setErrorMask(me, response.htmlStatus);
57 changeitem.update('');
89f57452 58 changeitem.setHidden(true);
a58001dd
DM
59 },
60 success: function(response, opts) {
61 var result = Ext.decode(response.responseText);
62 store.loadData(result.data);
63 var changes = result.changes;
64 if (changes === undefined || changes === '') {
65 changes = gettext("No changes");
89f57452 66 changeitem.setHidden(true);
21cd6c09 67 apply_btn.setDisabled(true);
03e93db5 68 revert_btn.setDisabled(true);
89f57452
DM
69 } else {
70 changeitem.update("<pre>" + Ext.htmlEncode(changes) + "</pre>");
71 changeitem.setHidden(false);
21cd6c09 72 apply_btn.setDisabled(false);
03e93db5 73 revert_btn.setDisabled(false);
a58001dd 74 }
a58001dd
DM
75 }
76 });
77 };
78
79 var run_editor = function() {
80 var grid = me.down('gridpanel');
81 var sm = grid.getSelectionModel();
82 var rec = sm.getSelection()[0];
83 if (!rec) {
84 return;
85 }
86
87 var win = Ext.create('Proxmox.node.NetworkEdit', {
88 nodename: me.nodename,
89 iface: rec.data.iface,
90 iftype: rec.data.type
91 });
92 win.show();
93 win.on('destroy', reload);
94 };
95
96 var edit_btn = new Ext.Button({
97 text: gettext('Edit'),
98 disabled: true,
99 handler: run_editor
100 });
101
102 var del_btn = new Ext.Button({
103 text: gettext('Remove'),
104 disabled: true,
105 handler: function(){
106 var grid = me.down('gridpanel');
107 var sm = grid.getSelectionModel();
108 var rec = sm.getSelection()[0];
109 if (!rec) {
110 return;
111 }
112
113 var iface = rec.data.iface;
114
115 Proxmox.Utils.API2Request({
116 url: baseUrl + '/' + iface,
117 method: 'DELETE',
118 waitMsgTarget: me,
119 callback: function() {
120 reload();
121 },
122 failure: function(response, opts) {
123 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
124 }
125 });
126 }
127 });
128
21cd6c09
DC
129 var apply_btn = Ext.create('Proxmox.button.Button', {
130 text: gettext('Apply Configuration'),
131 itemId: 'apply',
132 disabled: true,
2877ddea 133 confirmMsg: 'Do you want to apply pending network changes?',
21cd6c09
DC
134 hidden: !me.showApplyBtn,
135 handler: function() {
136 Proxmox.Utils.API2Request({
137 url: baseUrl,
138 method: 'PUT',
139 waitMsgTarget: me,
140 success: function(response, opts) {
141 var upid = response.result.data;
142
143 var win = Ext.create('Proxmox.window.TaskProgress', {
144 taskDone: reload,
145 upid: upid
146 });
147 win.show();
148 },
149 failure: function(response, opts) {
150 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
151 }
152 });
153 }
154 });
155
a58001dd
DM
156 var set_button_status = function() {
157 var grid = me.down('gridpanel');
158 var sm = grid.getSelectionModel();
159 var rec = sm.getSelection()[0];
160
161 edit_btn.setDisabled(!rec);
162 del_btn.setDisabled(!rec);
163 };
164
a58001dd
DM
165 var render_ports = function(value, metaData, record) {
166 if (value === 'bridge') {
167 return record.data.bridge_ports;
168 } else if (value === 'bond') {
169 return record.data.slaves;
170 } else if (value === 'OVSBridge') {
171 return record.data.ovs_ports;
172 } else if (value === 'OVSBond') {
173 return record.data.ovs_bonds;
174 }
175 };
176
177 var find_next_iface_id = function(prefix) {
178 var next;
179 for (next = 0; next <= 9999; next++) {
180 if (!store.getById(prefix + next.toString())) {
181 break;
182 }
183 }
184 return prefix + next.toString();
185 };
186
7c0e4c25
DC
187 var menu_items = [];
188
189 if (me.types.indexOf('bridge') !== -1) {
190 menu_items.push({
191 text: Proxmox.Utils.render_network_iface_type('bridge'),
192 handler: function() {
193 var win = Ext.create('Proxmox.node.NetworkEdit', {
194 nodename: me.nodename,
195 iftype: 'bridge',
196 iface_default: find_next_iface_id('vmbr')
197 });
198 win.on('destroy', reload);
199 win.show();
200 }
201 });
202 }
203
204 if (me.types.indexOf('bond') !== -1) {
205 menu_items.push({
206 text: Proxmox.Utils.render_network_iface_type('bond'),
207 handler: function() {
208 var win = Ext.create('Proxmox.node.NetworkEdit', {
209 nodename: me.nodename,
210 iftype: 'bond',
211 iface_default: find_next_iface_id('bond')
212 });
213 win.on('destroy', reload);
214 win.show();
215 }
216 });
217 }
218
8aefd47c
AD
219 if (me.types.indexOf('vlan') !== -1) {
220 menu_items.push({
221 text: Proxmox.Utils.render_network_iface_type('vlan'),
222 handler: function() {
223 var win = Ext.create('Proxmox.node.NetworkEdit', {
224 nodename: me.nodename,
225 iftype: 'vlan',
226 iface_default: 'interfaceX.1'
227 });
228 win.on('destroy', reload);
229 win.show();
230 }
231 });
232 }
233
7c0e4c25
DC
234 if (me.types.indexOf('ovs') !== -1) {
235 if (menu_items.length > 0) {
236 menu_items.push({ xtype: 'menuseparator' });
237 }
238
239 menu_items.push(
240 {
241 text: Proxmox.Utils.render_network_iface_type('OVSBridge'),
242 handler: function() {
243 var win = Ext.create('Proxmox.node.NetworkEdit', {
244 nodename: me.nodename,
245 iftype: 'OVSBridge',
246 iface_default: find_next_iface_id('vmbr')
247 });
248 win.on('destroy', reload);
249 win.show();
250 }
251 },
252 {
253 text: Proxmox.Utils.render_network_iface_type('OVSBond'),
254 handler: function() {
255 var win = Ext.create('Proxmox.node.NetworkEdit', {
256 nodename: me.nodename,
257 iftype: 'OVSBond',
258 iface_default: find_next_iface_id('bond')
259 });
260 win.on('destroy', reload);
261 win.show();
262 }
263 },
264 {
265 text: Proxmox.Utils.render_network_iface_type('OVSIntPort'),
266 handler: function() {
267 var win = Ext.create('Proxmox.node.NetworkEdit', {
268 nodename: me.nodename,
269 iftype: 'OVSIntPort'
270 });
271 win.on('destroy', reload);
272 win.show();
273 }
274 }
275 );
276 }
277
d0c2b878
DC
278 var renderer_generator = function(fieldname) {
279 return function(val, metaData, rec) {
280 var tmp = [];
281 if (rec.data[fieldname]) {
282 tmp.push(rec.data[fieldname]);
283 }
284 if (rec.data[fieldname + '6']) {
285 tmp.push(rec.data[fieldname + '6']);
286 }
287 return tmp.join('<br>') || '';
288 };
289 };
290
a58001dd
DM
291 Ext.apply(me, {
292 layout: 'border',
293 tbar: [
294 {
295 text: gettext('Create'),
7c0e4c25 296 menu: {
a58001dd 297 plain: true,
7c0e4c25
DC
298 items: menu_items
299 }
1cf31d6b 300 }, '-',
a58001dd
DM
301 {
302 text: gettext('Revert'),
03e93db5 303 itemId: 'revert',
a58001dd
DM
304 handler: function() {
305 Proxmox.Utils.API2Request({
306 url: baseUrl,
307 method: 'DELETE',
308 waitMsgTarget: me,
309 callback: function() {
310 reload();
311 },
312 failure: function(response, opts) {
313 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
314 }
315 });
316 }
317 },
318 edit_btn,
21cd6c09 319 del_btn,
1cf31d6b 320 '-',
21cd6c09 321 apply_btn
a58001dd
DM
322 ],
323 items: [
324 {
325 xtype: 'gridpanel',
326 stateful: true,
327 stateId: 'grid-node-network',
328 store: store,
329 region: 'center',
330 border: false,
331 columns: [
332 {
333 header: gettext('Name'),
a58001dd
DM
334 sortable: true,
335 dataIndex: 'iface'
336 },
337 {
338 header: gettext('Type'),
a58001dd 339 sortable: true,
869439b1 340 width: 120,
a58001dd
DM
341 renderer: Proxmox.Utils.render_network_iface_type,
342 dataIndex: 'type'
343 },
344 {
345 xtype: 'booleancolumn',
346 header: gettext('Active'),
347 width: 80,
348 sortable: true,
349 dataIndex: 'active',
9b575917
WL
350 trueText: Proxmox.Utils.yesText,
351 falseText: Proxmox.Utils.noText,
352 undefinedText: Proxmox.Utils.noText,
a58001dd
DM
353 },
354 {
355 xtype: 'booleancolumn',
356 header: gettext('Autostart'),
357 width: 80,
358 sortable: true,
359 dataIndex: 'autostart',
9b575917
WL
360 trueText: Proxmox.Utils.yesText,
361 falseText: Proxmox.Utils.noText,
362 undefinedText: Proxmox.Utils.noText
a58001dd 363 },
8947a4fc
WL
364 {
365 xtype: 'booleancolumn',
366 header: gettext('VLAN aware'),
367 width: 80,
368 sortable: true,
369 dataIndex: 'bridge_vlan_aware',
370 trueText: Proxmox.Utils.yesText,
371 falseText: Proxmox.Utils.noText,
372 undefinedText: Proxmox.Utils.noText
373 },
a58001dd
DM
374 {
375 header: gettext('Ports/Slaves'),
376 dataIndex: 'type',
377 renderer: render_ports
378 },
211bdf93
DC
379 {
380 header: gettext('Bond Mode'),
381 dataIndex: 'bond_mode',
382 renderer: Proxmox.Utils.render_bond_mode,
383 },
384 {
385 header: gettext('Hash Policy'),
386 hidden: true,
387 dataIndex: 'bond_xmit_hash_policy',
388 },
a58001dd
DM
389 {
390 header: gettext('IP address'),
391 sortable: true,
869439b1 392 width: 120,
4211996a 393 hidden: true,
a58001dd 394 dataIndex: 'address',
d0c2b878 395 renderer: renderer_generator('address'),
a58001dd
DM
396 },
397 {
398 header: gettext('Subnet mask'),
869439b1 399 width: 120,
a58001dd 400 sortable: true,
4211996a 401 hidden: true,
d0c2b878
DC
402 dataIndex: 'netmask',
403 renderer: renderer_generator('netmask'),
404 },
405 {
406 header: gettext('CIDR'),
407 width: 120,
408 sortable: true,
409 dataIndex: 'cidr',
410 renderer: renderer_generator('cidr'),
a58001dd
DM
411 },
412 {
413 header: gettext('Gateway'),
869439b1 414 width: 120,
a58001dd
DM
415 sortable: true,
416 dataIndex: 'gateway',
d0c2b878 417 renderer: renderer_generator('gateway'),
a58001dd
DM
418 },
419 {
420 header: gettext('Comment'),
421 dataIndex: 'comments',
869439b1 422 flex: 1,
a58001dd
DM
423 renderer: Ext.String.htmlEncode
424 }
425 ],
426 listeners: {
427 selectionchange: set_button_status,
428 itemdblclick: run_editor
429 }
430 },
431 {
432 border: false,
433 region: 'south',
434 autoScroll: true,
89f57452 435 hidden: true,
a58001dd
DM
436 itemId: 'changes',
437 tbar: [
438 gettext('Pending changes') + ' (' +
4beef5c4 439 gettext("Either reboot or use 'Apply Configuration' (needs ifupdown2) to activate") + ')'
a58001dd
DM
440 ],
441 split: true,
442 bodyPadding: 5,
443 flex: 0.6,
444 html: gettext("No changes")
445 }
446 ],
a58001dd
DM
447 });
448
449 me.callParent();
1a68e95d 450 reload();
a58001dd
DM
451 }
452});