1 Ext
.define('proxmox-networks', {
2 extend
: 'Ext.data.Model',
25 Ext
.define('Proxmox.node.NetworkView', {
26 extend
: 'Ext.panel.Panel',
28 alias
: ['widget.proxmoxNodeNetworkView'],
30 // defines what types of network devices we want to create
31 // order is always the same
32 types
: ['bridge', 'bond', 'vlan', 'ovs'],
36 initComponent: function() {
40 throw "no node name specified";
43 let baseUrl
= '/nodes/' + me
.nodename
+ '/network';
45 let store
= Ext
.create('Ext.data.Store', {
46 model
: 'proxmox-networks',
49 url
: '/api2/json' + baseUrl
,
59 let reload = function() {
60 let changeitem
= me
.down('#changes');
61 let apply_btn
= me
.down('#apply');
62 let revert_btn
= me
.down('#revert');
63 Proxmox
.Utils
.API2Request({
65 failure: function(response
, opts
) {
67 Proxmox
.Utils
.setErrorMask(me
, response
.htmlStatus
);
68 changeitem
.update('');
69 changeitem
.setHidden(true);
71 success: function(response
, opts
) {
72 let result
= Ext
.decode(response
.responseText
);
73 store
.loadData(result
.data
);
74 let changes
= result
.changes
;
75 if (changes
=== undefined || changes
=== '') {
76 changes
= gettext("No changes");
77 changeitem
.setHidden(true);
78 apply_btn
.setDisabled(true);
79 revert_btn
.setDisabled(true);
81 changeitem
.update("<pre>" + Ext
.htmlEncode(changes
) + "</pre>");
82 changeitem
.setHidden(false);
83 apply_btn
.setDisabled(false);
84 revert_btn
.setDisabled(false);
90 let run_editor = function() {
91 let grid
= me
.down('gridpanel');
92 let sm
= grid
.getSelectionModel();
93 let rec
= sm
.getSelection()[0];
98 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
99 nodename
: me
.nodename
,
100 iface
: rec
.data
.iface
,
101 iftype
: rec
.data
.type
,
104 win
.on('destroy', reload
);
107 let edit_btn
= new Ext
.Button({
108 text
: gettext('Edit'),
113 let del_btn
= new Ext
.Button({
114 text
: gettext('Remove'),
116 handler: function() {
117 let grid
= me
.down('gridpanel');
118 let sm
= grid
.getSelectionModel();
119 let rec
= sm
.getSelection()[0];
124 let iface
= rec
.data
.iface
;
126 Proxmox
.Utils
.API2Request({
127 url
: baseUrl
+ '/' + iface
,
130 callback: function() {
133 failure: function(response
, opts
) {
134 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
140 let apply_btn
= Ext
.create('Proxmox.button.Button', {
141 text
: gettext('Apply Configuration'),
144 confirmMsg
: 'Do you want to apply pending network changes?',
145 hidden
: !me
.showApplyBtn
,
146 handler: function() {
147 Proxmox
.Utils
.API2Request({
151 success: function(response
, opts
) {
152 let upid
= response
.result
.data
;
154 let win
= Ext
.create('Proxmox.window.TaskProgress', {
160 failure: function(response
, opts
) {
161 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
167 let set_button_status = function() {
168 let grid
= me
.down('gridpanel');
169 let sm
= grid
.getSelectionModel();
170 let rec
= sm
.getSelection()[0];
172 edit_btn
.setDisabled(!rec
);
173 del_btn
.setDisabled(!rec
);
176 let render_ports = function(value
, metaData
, record
) {
177 if (value
=== 'bridge') {
178 return record
.data
.bridge_ports
;
179 } else if (value
=== 'bond') {
180 return record
.data
.slaves
;
181 } else if (value
=== 'OVSBridge') {
182 return record
.data
.ovs_ports
;
183 } else if (value
=== 'OVSBond') {
184 return record
.data
.ovs_bonds
;
189 let find_next_iface_id = function(prefix
) {
191 for (next
= 0; next
<= 9999; next
++) {
192 if (!store
.getById(prefix
+ next
.toString())) {
196 return prefix
+ next
.toString();
201 if (me
.types
.indexOf('bridge') !== -1) {
203 text
: Proxmox
.Utils
.render_network_iface_type('bridge'),
204 handler: function() {
205 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
206 nodename
: me
.nodename
,
208 iface_default
: find_next_iface_id('vmbr'),
209 onlineHelp
: 'sysadmin_network_configuration',
211 win
.on('destroy', reload
);
217 if (me
.types
.indexOf('bond') !== -1) {
219 text
: Proxmox
.Utils
.render_network_iface_type('bond'),
220 handler: function() {
221 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
222 nodename
: me
.nodename
,
224 iface_default
: find_next_iface_id('bond'),
225 onlineHelp
: 'sysadmin_network_configuration',
227 win
.on('destroy', reload
);
233 if (me
.types
.indexOf('vlan') !== -1) {
235 text
: Proxmox
.Utils
.render_network_iface_type('vlan'),
236 handler: function() {
237 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
238 nodename
: me
.nodename
,
240 iface_default
: find_next_iface_id('vlan'),
241 onlineHelp
: 'sysadmin_network_configuration',
243 win
.on('destroy', reload
);
249 if (me
.types
.indexOf('ovs') !== -1) {
250 if (menu_items
.length
> 0) {
251 menu_items
.push({ xtype
: 'menuseparator' });
256 text
: Proxmox
.Utils
.render_network_iface_type('OVSBridge'),
257 handler: function() {
258 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
259 nodename
: me
.nodename
,
261 iface_default
: find_next_iface_id('vmbr'),
263 win
.on('destroy', reload
);
268 text
: Proxmox
.Utils
.render_network_iface_type('OVSBond'),
269 handler: function() {
270 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
271 nodename
: me
.nodename
,
273 iface_default
: find_next_iface_id('bond'),
275 win
.on('destroy', reload
);
280 text
: Proxmox
.Utils
.render_network_iface_type('OVSIntPort'),
281 handler: function() {
282 let win
= Ext
.create('Proxmox.node.NetworkEdit', {
283 nodename
: me
.nodename
,
284 iftype
: 'OVSIntPort',
286 win
.on('destroy', reload
);
293 let renderer_generator = function(fieldname
) {
294 return function(val
, metaData
, rec
) {
296 if (rec
.data
[fieldname
]) {
297 tmp
.push(rec
.data
[fieldname
]);
299 if (rec
.data
[fieldname
+ '6']) {
300 tmp
.push(rec
.data
[fieldname
+ '6']);
302 return tmp
.join('<br>') || '';
310 text
: gettext('Create'),
317 text
: gettext('Revert'),
319 handler: function() {
320 Proxmox
.Utils
.API2Request({
324 callback: function() {
327 failure: function(response
, opts
) {
328 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
342 stateId
: 'grid-node-network',
348 header
: gettext('Name'),
353 header
: gettext('Type'),
356 renderer
: Proxmox
.Utils
.render_network_iface_type
,
360 xtype
: 'booleancolumn',
361 header
: gettext('Active'),
365 trueText
: Proxmox
.Utils
.yesText
,
366 falseText
: Proxmox
.Utils
.noText
,
367 undefinedText
: Proxmox
.Utils
.noText
,
370 xtype
: 'booleancolumn',
371 header
: gettext('Autostart'),
374 dataIndex
: 'autostart',
375 trueText
: Proxmox
.Utils
.yesText
,
376 falseText
: Proxmox
.Utils
.noText
,
377 undefinedText
: Proxmox
.Utils
.noText
,
380 xtype
: 'booleancolumn',
381 header
: gettext('VLAN aware'),
384 dataIndex
: 'bridge_vlan_aware',
385 trueText
: Proxmox
.Utils
.yesText
,
386 falseText
: Proxmox
.Utils
.noText
,
387 undefinedText
: Proxmox
.Utils
.noText
,
390 header
: gettext('Ports/Slaves'),
392 renderer
: render_ports
,
395 header
: gettext('Bond Mode'),
396 dataIndex
: 'bond_mode',
397 renderer
: Proxmox
.Utils
.render_bond_mode
,
400 header
: gettext('Hash Policy'),
402 dataIndex
: 'bond_xmit_hash_policy',
405 header
: gettext('IP address'),
409 dataIndex
: 'address',
410 renderer
: renderer_generator('address'),
413 header
: gettext('Subnet mask'),
417 dataIndex
: 'netmask',
418 renderer
: renderer_generator('netmask'),
421 header
: gettext('CIDR'),
425 renderer
: renderer_generator('cidr'),
428 header
: gettext('Gateway'),
431 dataIndex
: 'gateway',
432 renderer
: renderer_generator('gateway'),
435 header
: gettext('VLAN ID'),
438 dataIndex
: 'vlan-id',
441 header
: gettext('VLAN raw device'),
444 dataIndex
: 'vlan-raw-device',
447 header
: gettext('Comment'),
448 dataIndex
: 'comments',
450 renderer
: Ext
.String
.htmlEncode
,
454 selectionchange
: set_button_status
,
455 itemdblclick
: run_editor
,
465 gettext('Pending changes') + ' (' +
466 gettext("Either reboot or use 'Apply Configuration' (needs ifupdown2) to activate") + ')',
471 html
: gettext("No changes"),