]>
Commit | Line | Data |
---|---|---|
a58001dd DM |
1 | Ext.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', | |
8 | 'comments' | |
9 | ], | |
10 | idProperty: 'iface' | |
11 | }); | |
12 | ||
13 | Ext.define('Proxmox.node.NetworkView', { | |
14 | extend: 'Ext.panel.Panel', | |
15 | ||
16 | alias: ['widget.proxmoxNodeNetworkView'], | |
17 | ||
7c0e4c25 DC |
18 | // defines what types of network devices we want to create |
19 | // order is always the same | |
20 | types: ['bridge', 'bond', 'ovs'], | |
21 | ||
a58001dd DM |
22 | initComponent : function() { |
23 | var me = this; | |
24 | ||
25 | if (!me.nodename) { | |
26 | throw "no node name specified"; | |
27 | } | |
28 | ||
29 | var baseUrl = '/nodes/' + me.nodename + '/network'; | |
30 | ||
31 | var store = Ext.create('Ext.data.Store', { | |
32 | model: 'proxmox-networks', | |
33 | proxy: { | |
34 | type: 'proxmox', | |
35 | url: '/api2/json' + baseUrl | |
36 | }, | |
37 | sorters: [ | |
38 | { | |
39 | property : 'iface', | |
40 | direction: 'ASC' | |
41 | } | |
42 | ] | |
43 | }); | |
44 | ||
45 | var reload = function() { | |
46 | var changeitem = me.down('#changes'); | |
47 | Proxmox.Utils.API2Request({ | |
48 | url: baseUrl, | |
49 | failure: function(response, opts) { | |
a58001dd | 50 | store.loadData({}); |
b81cf173 DM |
51 | Proxmox.Utils.setErrorMask(me, response.htmlStatus); |
52 | changeitem.update(''); | |
89f57452 | 53 | changeitem.setHidden(true); |
a58001dd DM |
54 | }, |
55 | success: function(response, opts) { | |
56 | var result = Ext.decode(response.responseText); | |
57 | store.loadData(result.data); | |
58 | var changes = result.changes; | |
59 | if (changes === undefined || changes === '') { | |
60 | changes = gettext("No changes"); | |
89f57452 DM |
61 | changeitem.setHidden(true); |
62 | } else { | |
63 | changeitem.update("<pre>" + Ext.htmlEncode(changes) + "</pre>"); | |
64 | changeitem.setHidden(false); | |
a58001dd | 65 | } |
a58001dd DM |
66 | } |
67 | }); | |
68 | }; | |
69 | ||
70 | var run_editor = function() { | |
71 | var grid = me.down('gridpanel'); | |
72 | var sm = grid.getSelectionModel(); | |
73 | var rec = sm.getSelection()[0]; | |
74 | if (!rec) { | |
75 | return; | |
76 | } | |
77 | ||
78 | var win = Ext.create('Proxmox.node.NetworkEdit', { | |
79 | nodename: me.nodename, | |
80 | iface: rec.data.iface, | |
81 | iftype: rec.data.type | |
82 | }); | |
83 | win.show(); | |
84 | win.on('destroy', reload); | |
85 | }; | |
86 | ||
87 | var edit_btn = new Ext.Button({ | |
88 | text: gettext('Edit'), | |
89 | disabled: true, | |
90 | handler: run_editor | |
91 | }); | |
92 | ||
93 | var del_btn = new Ext.Button({ | |
94 | text: gettext('Remove'), | |
95 | disabled: true, | |
96 | handler: function(){ | |
97 | var grid = me.down('gridpanel'); | |
98 | var sm = grid.getSelectionModel(); | |
99 | var rec = sm.getSelection()[0]; | |
100 | if (!rec) { | |
101 | return; | |
102 | } | |
103 | ||
104 | var iface = rec.data.iface; | |
105 | ||
106 | Proxmox.Utils.API2Request({ | |
107 | url: baseUrl + '/' + iface, | |
108 | method: 'DELETE', | |
109 | waitMsgTarget: me, | |
110 | callback: function() { | |
111 | reload(); | |
112 | }, | |
113 | failure: function(response, opts) { | |
114 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
115 | } | |
116 | }); | |
117 | } | |
118 | }); | |
119 | ||
120 | var set_button_status = function() { | |
121 | var grid = me.down('gridpanel'); | |
122 | var sm = grid.getSelectionModel(); | |
123 | var rec = sm.getSelection()[0]; | |
124 | ||
125 | edit_btn.setDisabled(!rec); | |
126 | del_btn.setDisabled(!rec); | |
127 | }; | |
128 | ||
a58001dd DM |
129 | var render_ports = function(value, metaData, record) { |
130 | if (value === 'bridge') { | |
131 | return record.data.bridge_ports; | |
132 | } else if (value === 'bond') { | |
133 | return record.data.slaves; | |
134 | } else if (value === 'OVSBridge') { | |
135 | return record.data.ovs_ports; | |
136 | } else if (value === 'OVSBond') { | |
137 | return record.data.ovs_bonds; | |
138 | } | |
139 | }; | |
140 | ||
141 | var find_next_iface_id = function(prefix) { | |
142 | var next; | |
143 | for (next = 0; next <= 9999; next++) { | |
144 | if (!store.getById(prefix + next.toString())) { | |
145 | break; | |
146 | } | |
147 | } | |
148 | return prefix + next.toString(); | |
149 | }; | |
150 | ||
7c0e4c25 DC |
151 | var menu_items = []; |
152 | ||
153 | if (me.types.indexOf('bridge') !== -1) { | |
154 | menu_items.push({ | |
155 | text: Proxmox.Utils.render_network_iface_type('bridge'), | |
156 | handler: function() { | |
157 | var win = Ext.create('Proxmox.node.NetworkEdit', { | |
158 | nodename: me.nodename, | |
159 | iftype: 'bridge', | |
160 | iface_default: find_next_iface_id('vmbr') | |
161 | }); | |
162 | win.on('destroy', reload); | |
163 | win.show(); | |
164 | } | |
165 | }); | |
166 | } | |
167 | ||
168 | if (me.types.indexOf('bond') !== -1) { | |
169 | menu_items.push({ | |
170 | text: Proxmox.Utils.render_network_iface_type('bond'), | |
171 | handler: function() { | |
172 | var win = Ext.create('Proxmox.node.NetworkEdit', { | |
173 | nodename: me.nodename, | |
174 | iftype: 'bond', | |
175 | iface_default: find_next_iface_id('bond') | |
176 | }); | |
177 | win.on('destroy', reload); | |
178 | win.show(); | |
179 | } | |
180 | }); | |
181 | } | |
182 | ||
183 | if (me.types.indexOf('ovs') !== -1) { | |
184 | if (menu_items.length > 0) { | |
185 | menu_items.push({ xtype: 'menuseparator' }); | |
186 | } | |
187 | ||
188 | menu_items.push( | |
189 | { | |
190 | text: Proxmox.Utils.render_network_iface_type('OVSBridge'), | |
191 | handler: function() { | |
192 | var win = Ext.create('Proxmox.node.NetworkEdit', { | |
193 | nodename: me.nodename, | |
194 | iftype: 'OVSBridge', | |
195 | iface_default: find_next_iface_id('vmbr') | |
196 | }); | |
197 | win.on('destroy', reload); | |
198 | win.show(); | |
199 | } | |
200 | }, | |
201 | { | |
202 | text: Proxmox.Utils.render_network_iface_type('OVSBond'), | |
203 | handler: function() { | |
204 | var win = Ext.create('Proxmox.node.NetworkEdit', { | |
205 | nodename: me.nodename, | |
206 | iftype: 'OVSBond', | |
207 | iface_default: find_next_iface_id('bond') | |
208 | }); | |
209 | win.on('destroy', reload); | |
210 | win.show(); | |
211 | } | |
212 | }, | |
213 | { | |
214 | text: Proxmox.Utils.render_network_iface_type('OVSIntPort'), | |
215 | handler: function() { | |
216 | var win = Ext.create('Proxmox.node.NetworkEdit', { | |
217 | nodename: me.nodename, | |
218 | iftype: 'OVSIntPort' | |
219 | }); | |
220 | win.on('destroy', reload); | |
221 | win.show(); | |
222 | } | |
223 | } | |
224 | ); | |
225 | } | |
226 | ||
a58001dd DM |
227 | Ext.apply(me, { |
228 | layout: 'border', | |
229 | tbar: [ | |
230 | { | |
231 | text: gettext('Create'), | |
7c0e4c25 | 232 | menu: { |
a58001dd | 233 | plain: true, |
7c0e4c25 DC |
234 | items: menu_items |
235 | } | |
a58001dd DM |
236 | }, ' ', |
237 | { | |
238 | text: gettext('Revert'), | |
239 | handler: function() { | |
240 | Proxmox.Utils.API2Request({ | |
241 | url: baseUrl, | |
242 | method: 'DELETE', | |
243 | waitMsgTarget: me, | |
244 | callback: function() { | |
245 | reload(); | |
246 | }, | |
247 | failure: function(response, opts) { | |
248 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
249 | } | |
250 | }); | |
251 | } | |
252 | }, | |
253 | edit_btn, | |
254 | del_btn | |
255 | ], | |
256 | items: [ | |
257 | { | |
258 | xtype: 'gridpanel', | |
259 | stateful: true, | |
260 | stateId: 'grid-node-network', | |
261 | store: store, | |
262 | region: 'center', | |
263 | border: false, | |
264 | columns: [ | |
265 | { | |
266 | header: gettext('Name'), | |
a58001dd DM |
267 | sortable: true, |
268 | dataIndex: 'iface' | |
269 | }, | |
270 | { | |
271 | header: gettext('Type'), | |
a58001dd | 272 | sortable: true, |
869439b1 | 273 | width: 120, |
a58001dd DM |
274 | renderer: Proxmox.Utils.render_network_iface_type, |
275 | dataIndex: 'type' | |
276 | }, | |
277 | { | |
278 | xtype: 'booleancolumn', | |
279 | header: gettext('Active'), | |
280 | width: 80, | |
281 | sortable: true, | |
282 | dataIndex: 'active', | |
283 | trueText: 'Yes', | |
284 | falseText: 'No', | |
285 | undefinedText: 'No' | |
286 | }, | |
287 | { | |
288 | xtype: 'booleancolumn', | |
289 | header: gettext('Autostart'), | |
290 | width: 80, | |
291 | sortable: true, | |
292 | dataIndex: 'autostart', | |
293 | trueText: 'Yes', | |
294 | falseText: 'No', | |
295 | undefinedText: 'No' | |
296 | }, | |
297 | { | |
298 | header: gettext('Ports/Slaves'), | |
299 | dataIndex: 'type', | |
300 | renderer: render_ports | |
301 | }, | |
302 | { | |
303 | header: gettext('IP address'), | |
304 | sortable: true, | |
869439b1 | 305 | width: 120, |
a58001dd DM |
306 | dataIndex: 'address', |
307 | renderer: function(value, metaData, rec) { | |
308 | if (rec.data.address && rec.data.address6) { | |
309 | return rec.data.address + "<br>" | |
310 | + rec.data.address6 + '/' + rec.data.netmask6; | |
311 | } else if (rec.data.address6) { | |
312 | return rec.data.address6 + '/' + rec.data.netmask6; | |
313 | } else { | |
314 | return rec.data.address; | |
315 | } | |
316 | } | |
317 | }, | |
318 | { | |
319 | header: gettext('Subnet mask'), | |
869439b1 | 320 | width: 120, |
a58001dd DM |
321 | sortable: true, |
322 | dataIndex: 'netmask' | |
323 | }, | |
324 | { | |
325 | header: gettext('Gateway'), | |
869439b1 | 326 | width: 120, |
a58001dd DM |
327 | sortable: true, |
328 | dataIndex: 'gateway', | |
329 | renderer: function(value, metaData, rec) { | |
330 | if (rec.data.gateway && rec.data.gateway6) { | |
331 | return rec.data.gateway + "<br>" + rec.data.gateway6; | |
332 | } else if (rec.data.gateway6) { | |
333 | return rec.data.gateway6; | |
334 | } else { | |
335 | return rec.data.gateway; | |
336 | } | |
337 | } | |
338 | }, | |
339 | { | |
340 | header: gettext('Comment'), | |
341 | dataIndex: 'comments', | |
869439b1 | 342 | flex: 1, |
a58001dd DM |
343 | renderer: Ext.String.htmlEncode |
344 | } | |
345 | ], | |
346 | listeners: { | |
347 | selectionchange: set_button_status, | |
348 | itemdblclick: run_editor | |
349 | } | |
350 | }, | |
351 | { | |
352 | border: false, | |
353 | region: 'south', | |
354 | autoScroll: true, | |
89f57452 | 355 | hidden: true, |
a58001dd DM |
356 | itemId: 'changes', |
357 | tbar: [ | |
358 | gettext('Pending changes') + ' (' + | |
359 | gettext('Please reboot to activate changes') + ')' | |
360 | ], | |
361 | split: true, | |
362 | bodyPadding: 5, | |
363 | flex: 0.6, | |
364 | html: gettext("No changes") | |
365 | } | |
366 | ], | |
a58001dd DM |
367 | }); |
368 | ||
369 | me.callParent(); | |
1a68e95d | 370 | reload(); |
a58001dd DM |
371 | } |
372 | }); |