]> git.proxmox.com Git - proxmox-widget-toolkit.git/blame - node/NetworkView.js
window/Edit: accept bodyPadding from config
[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',
25f37cbf
TL
196 iface_default: find_next_iface_id('vmbr'),
197 onlineHelp: 'sysadmin_network_configuration',
7c0e4c25
DC
198 });
199 win.on('destroy', reload);
200 win.show();
201 }
202 });
203 }
204
205 if (me.types.indexOf('bond') !== -1) {
206 menu_items.push({
207 text: Proxmox.Utils.render_network_iface_type('bond'),
208 handler: function() {
209 var win = Ext.create('Proxmox.node.NetworkEdit', {
210 nodename: me.nodename,
211 iftype: 'bond',
25f37cbf
TL
212 iface_default: find_next_iface_id('bond'),
213 onlineHelp: 'sysadmin_network_configuration',
7c0e4c25
DC
214 });
215 win.on('destroy', reload);
216 win.show();
217 }
218 });
219 }
220
8aefd47c
AD
221 if (me.types.indexOf('vlan') !== -1) {
222 menu_items.push({
223 text: Proxmox.Utils.render_network_iface_type('vlan'),
224 handler: function() {
225 var win = Ext.create('Proxmox.node.NetworkEdit', {
226 nodename: me.nodename,
227 iftype: 'vlan',
25f37cbf
TL
228 iface_default: 'interfaceX.1',
229 onlineHelp: 'sysadmin_network_configuration',
8aefd47c
AD
230 });
231 win.on('destroy', reload);
232 win.show();
233 }
234 });
235 }
236
7c0e4c25
DC
237 if (me.types.indexOf('ovs') !== -1) {
238 if (menu_items.length > 0) {
239 menu_items.push({ xtype: 'menuseparator' });
240 }
241
242 menu_items.push(
243 {
244 text: Proxmox.Utils.render_network_iface_type('OVSBridge'),
245 handler: function() {
246 var win = Ext.create('Proxmox.node.NetworkEdit', {
247 nodename: me.nodename,
248 iftype: 'OVSBridge',
249 iface_default: find_next_iface_id('vmbr')
250 });
251 win.on('destroy', reload);
252 win.show();
253 }
254 },
255 {
256 text: Proxmox.Utils.render_network_iface_type('OVSBond'),
257 handler: function() {
258 var win = Ext.create('Proxmox.node.NetworkEdit', {
259 nodename: me.nodename,
260 iftype: 'OVSBond',
261 iface_default: find_next_iface_id('bond')
262 });
263 win.on('destroy', reload);
264 win.show();
265 }
266 },
267 {
268 text: Proxmox.Utils.render_network_iface_type('OVSIntPort'),
269 handler: function() {
270 var win = Ext.create('Proxmox.node.NetworkEdit', {
271 nodename: me.nodename,
272 iftype: 'OVSIntPort'
273 });
274 win.on('destroy', reload);
275 win.show();
276 }
277 }
278 );
279 }
280
d0c2b878
DC
281 var renderer_generator = function(fieldname) {
282 return function(val, metaData, rec) {
283 var tmp = [];
284 if (rec.data[fieldname]) {
285 tmp.push(rec.data[fieldname]);
286 }
287 if (rec.data[fieldname + '6']) {
288 tmp.push(rec.data[fieldname + '6']);
289 }
290 return tmp.join('<br>') || '';
291 };
292 };
293
a58001dd
DM
294 Ext.apply(me, {
295 layout: 'border',
296 tbar: [
297 {
298 text: gettext('Create'),
7c0e4c25 299 menu: {
a58001dd 300 plain: true,
7c0e4c25
DC
301 items: menu_items
302 }
1cf31d6b 303 }, '-',
a58001dd
DM
304 {
305 text: gettext('Revert'),
03e93db5 306 itemId: 'revert',
a58001dd
DM
307 handler: function() {
308 Proxmox.Utils.API2Request({
309 url: baseUrl,
310 method: 'DELETE',
311 waitMsgTarget: me,
312 callback: function() {
313 reload();
314 },
315 failure: function(response, opts) {
316 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
317 }
318 });
319 }
320 },
321 edit_btn,
21cd6c09 322 del_btn,
1cf31d6b 323 '-',
21cd6c09 324 apply_btn
a58001dd
DM
325 ],
326 items: [
327 {
328 xtype: 'gridpanel',
329 stateful: true,
330 stateId: 'grid-node-network',
331 store: store,
332 region: 'center',
333 border: false,
334 columns: [
335 {
336 header: gettext('Name'),
a58001dd
DM
337 sortable: true,
338 dataIndex: 'iface'
339 },
340 {
341 header: gettext('Type'),
a58001dd 342 sortable: true,
869439b1 343 width: 120,
a58001dd
DM
344 renderer: Proxmox.Utils.render_network_iface_type,
345 dataIndex: 'type'
346 },
347 {
348 xtype: 'booleancolumn',
349 header: gettext('Active'),
350 width: 80,
351 sortable: true,
352 dataIndex: 'active',
9b575917
WL
353 trueText: Proxmox.Utils.yesText,
354 falseText: Proxmox.Utils.noText,
355 undefinedText: Proxmox.Utils.noText,
a58001dd
DM
356 },
357 {
358 xtype: 'booleancolumn',
359 header: gettext('Autostart'),
360 width: 80,
361 sortable: true,
362 dataIndex: 'autostart',
9b575917
WL
363 trueText: Proxmox.Utils.yesText,
364 falseText: Proxmox.Utils.noText,
365 undefinedText: Proxmox.Utils.noText
a58001dd 366 },
8947a4fc
WL
367 {
368 xtype: 'booleancolumn',
369 header: gettext('VLAN aware'),
370 width: 80,
371 sortable: true,
372 dataIndex: 'bridge_vlan_aware',
373 trueText: Proxmox.Utils.yesText,
374 falseText: Proxmox.Utils.noText,
375 undefinedText: Proxmox.Utils.noText
376 },
a58001dd
DM
377 {
378 header: gettext('Ports/Slaves'),
379 dataIndex: 'type',
380 renderer: render_ports
381 },
211bdf93
DC
382 {
383 header: gettext('Bond Mode'),
384 dataIndex: 'bond_mode',
385 renderer: Proxmox.Utils.render_bond_mode,
386 },
387 {
388 header: gettext('Hash Policy'),
389 hidden: true,
390 dataIndex: 'bond_xmit_hash_policy',
391 },
a58001dd
DM
392 {
393 header: gettext('IP address'),
394 sortable: true,
869439b1 395 width: 120,
4211996a 396 hidden: true,
a58001dd 397 dataIndex: 'address',
d0c2b878 398 renderer: renderer_generator('address'),
a58001dd
DM
399 },
400 {
401 header: gettext('Subnet mask'),
869439b1 402 width: 120,
a58001dd 403 sortable: true,
4211996a 404 hidden: true,
d0c2b878
DC
405 dataIndex: 'netmask',
406 renderer: renderer_generator('netmask'),
407 },
408 {
409 header: gettext('CIDR'),
410 width: 120,
411 sortable: true,
412 dataIndex: 'cidr',
413 renderer: renderer_generator('cidr'),
a58001dd
DM
414 },
415 {
416 header: gettext('Gateway'),
869439b1 417 width: 120,
a58001dd
DM
418 sortable: true,
419 dataIndex: 'gateway',
d0c2b878 420 renderer: renderer_generator('gateway'),
a58001dd
DM
421 },
422 {
423 header: gettext('Comment'),
424 dataIndex: 'comments',
869439b1 425 flex: 1,
a58001dd
DM
426 renderer: Ext.String.htmlEncode
427 }
428 ],
429 listeners: {
430 selectionchange: set_button_status,
431 itemdblclick: run_editor
432 }
433 },
434 {
435 border: false,
436 region: 'south',
437 autoScroll: true,
89f57452 438 hidden: true,
a58001dd
DM
439 itemId: 'changes',
440 tbar: [
441 gettext('Pending changes') + ' (' +
4beef5c4 442 gettext("Either reboot or use 'Apply Configuration' (needs ifupdown2) to activate") + ')'
a58001dd
DM
443 ],
444 split: true,
445 bodyPadding: 5,
446 flex: 0.6,
447 html: gettext("No changes")
448 }
449 ],
a58001dd
DM
450 });
451
452 me.callParent();
1a68e95d 453 reload();
a58001dd
DM
454 }
455});