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