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