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