]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/Network.js
gui: lxc/Network: remove trailing whitespace
[pve-manager.git] / www / manager6 / lxc / Network.js
1 Ext.define('PVE.lxc.NetworkInputPanel', {
2 extend: 'Proxmox.panel.InputPanel',
3 alias: 'widget.pveLxcNetworkInputPanel',
4
5 insideWizard: false,
6
7 onlineHelp: 'pct_container_network',
8
9 setNodename: function(nodename) {
10 var me = this;
11
12 if (!nodename || (me.nodename === nodename)) {
13 return;
14 }
15
16 me.nodename = nodename;
17
18 var bridgesel = me.query("[isFormField][name=bridge]")[0];
19 bridgesel.setNodename(nodename);
20 },
21
22 onGetValues: function(values) {
23 var me = this;
24
25 var id;
26 if (me.isCreate) {
27 id = values.id;
28 delete values.id;
29 } else {
30 id = me.ifname;
31 }
32
33 if (!id) {
34 return {};
35 }
36
37 var newdata = {};
38
39 if (values.ipv6mode !== 'static') {
40 values.ip6 = values.ipv6mode;
41 }
42 if (values.ipv4mode !== 'static') {
43 values.ip = values.ipv4mode;
44 }
45 newdata[id] = PVE.Parser.printLxcNetwork(values);
46 return newdata;
47 },
48
49 initComponent : function() {
50 var me = this;
51
52 var cdata = {};
53
54 if (me.insideWizard) {
55 me.ifname = 'net0';
56 cdata.name = 'eth0';
57 me.dataCache = {};
58 }
59 cdata.firewall = (me.insideWizard || me.isCreate);
60
61 if (!me.dataCache) {
62 throw "no dataCache specified";
63 }
64
65 if (!me.isCreate) {
66 if (!me.ifname) {
67 throw "no interface name specified";
68 }
69 if (!me.dataCache[me.ifname]) {
70 throw "no such interface '" + me.ifname + "'";
71 }
72
73 cdata = PVE.Parser.parseLxcNetwork(me.dataCache[me.ifname]);
74 }
75
76 var i;
77 for (i = 0; i < 10; i++) {
78 if (me.isCreate && !me.dataCache['net'+i.toString()]) {
79 me.ifname = 'net' + i.toString();
80 break;
81 }
82 }
83
84 var idselector = {
85 xtype: 'hidden',
86 name: 'id',
87 value: me.ifname
88 };
89
90 me.column1 = [
91 idselector,
92 {
93 xtype: 'textfield',
94 name: 'name',
95 fieldLabel: gettext('Name'),
96 emptyText: '(e.g., eth0)',
97 allowBlank: false,
98 value: cdata.name,
99 validator: function(value) {
100 var result = '';
101 Ext.Object.each(me.dataCache, function(key, netstr) {
102 if (!key.match(/^net\d+/) || key === me.ifname) {
103 return; // continue
104 }
105 var net = PVE.Parser.parseLxcNetwork(netstr);
106 if (net.name === value) {
107 result = "interface name already in use";
108 return false;
109 }
110 });
111 if (result !== '') {
112 return result;
113 }
114 // validator can return bool/string
115 /*jslint confusion:true*/
116 return true;
117 }
118 },
119 {
120 xtype: 'textfield',
121 name: 'hwaddr',
122 fieldLabel: gettext('MAC address'),
123 vtype: 'MacAddress',
124 value: cdata.hwaddr,
125 allowBlank: true,
126 emptyText: 'auto'
127 },
128 {
129 xtype: 'PVE.form.BridgeSelector',
130 name: 'bridge',
131 nodename: me.nodename,
132 fieldLabel: gettext('Bridge'),
133 value: cdata.bridge,
134 allowBlank: false
135 },
136 {
137 xtype: 'pveVlanField',
138 name: 'tag',
139 value: cdata.tag
140 },
141 {
142 xtype: 'numberfield',
143 name: 'rate',
144 fieldLabel: gettext('Rate limit') + ' (MB/s)',
145 minValue: 0,
146 maxValue: 10*1024,
147 value: cdata.rate,
148 emptyText: 'unlimited',
149 allowBlank: true
150 },
151 {
152 xtype: 'proxmoxcheckbox',
153 fieldLabel: gettext('Firewall'),
154 name: 'firewall',
155 value: cdata.firewall
156 }
157 ];
158
159 var dhcp4 = (cdata.ip === 'dhcp');
160 if (dhcp4) {
161 cdata.ip = '';
162 cdata.gw = '';
163 }
164
165 var auto6 = (cdata.ip6 === 'auto');
166 var dhcp6 = (cdata.ip6 === 'dhcp');
167 if (auto6 || dhcp6) {
168 cdata.ip6 = '';
169 cdata.gw6 = '';
170 }
171
172 me.column2 = [
173 {
174 layout: {
175 type: 'hbox',
176 align: 'middle'
177 },
178 border: false,
179 margin: '0 0 5 0',
180 items: [
181 {
182 xtype: 'label',
183 text: 'IPv4:' // do not localize
184 },
185 {
186 xtype: 'radiofield',
187 boxLabel: gettext('Static'),
188 name: 'ipv4mode',
189 inputValue: 'static',
190 checked: !dhcp4,
191 margin: '0 0 0 10',
192 listeners: {
193 change: function(cb, value) {
194 me.down('field[name=ip]').setDisabled(!value);
195 me.down('field[name=gw]').setDisabled(!value);
196 }
197 }
198 },
199 {
200 xtype: 'radiofield',
201 boxLabel: 'DHCP', // do not localize
202 name: 'ipv4mode',
203 inputValue: 'dhcp',
204 checked: dhcp4,
205 margin: '0 0 0 10'
206 }
207 ]
208 },
209 {
210 xtype: 'textfield',
211 name: 'ip',
212 vtype: 'IPCIDRAddress',
213 value: cdata.ip,
214 disabled: dhcp4,
215 fieldLabel: 'IPv4/CIDR' // do not localize
216 },
217 {
218 xtype: 'textfield',
219 name: 'gw',
220 value: cdata.gw,
221 vtype: 'IPAddress',
222 disabled: dhcp4,
223 fieldLabel: gettext('Gateway') + ' (IPv4)',
224 margin: '0 0 3 0' // override bottom margin to account for the menuseparator
225 },
226 {
227 xtype: 'menuseparator',
228 height: '3',
229 margin: '0'
230 },
231 {
232 layout: {
233 type: 'hbox',
234 align: 'middle'
235 },
236 border: false,
237 margin: '0 0 5 0',
238 items: [
239 {
240 xtype: 'label',
241 text: 'IPv6:' // do not localize
242 },
243 {
244 xtype: 'radiofield',
245 boxLabel: gettext('Static'),
246 name: 'ipv6mode',
247 inputValue: 'static',
248 checked: !(auto6 || dhcp6),
249 margin: '0 0 0 10',
250 listeners: {
251 change: function(cb, value) {
252 me.down('field[name=ip6]').setDisabled(!value);
253 me.down('field[name=gw6]').setDisabled(!value);
254 }
255 }
256 },
257 {
258 xtype: 'radiofield',
259 boxLabel: 'DHCP', // do not localize
260 name: 'ipv6mode',
261 inputValue: 'dhcp',
262 checked: dhcp6,
263 margin: '0 0 0 10'
264 },
265 {
266 xtype: 'radiofield',
267 boxLabel: 'SLAAC', // do not localize
268 name: 'ipv6mode',
269 inputValue: 'auto',
270 checked: auto6,
271 margin: '0 0 0 10'
272 }
273 ]
274 },
275 {
276 xtype: 'textfield',
277 name: 'ip6',
278 value: cdata.ip6,
279 vtype: 'IP6CIDRAddress',
280 disabled: (dhcp6 || auto6),
281 fieldLabel: 'IPv6/CIDR' // do not localize
282 },
283 {
284 xtype: 'textfield',
285 name: 'gw6',
286 vtype: 'IP6Address',
287 value: cdata.gw6,
288 disabled: (dhcp6 || auto6),
289 fieldLabel: gettext('Gateway') + ' (IPv6)'
290 }
291 ];
292
293 me.callParent();
294 }
295 });
296
297 Ext.define('PVE.lxc.NetworkEdit', {
298 extend: 'Proxmox.window.Edit',
299
300 isAdd: true,
301
302 initComponent : function() {
303 var me = this;
304
305 if (!me.dataCache) {
306 throw "no dataCache specified";
307 }
308
309 if (!me.nodename) {
310 throw "no node name specified";
311 }
312
313 var ipanel = Ext.create('PVE.lxc.NetworkInputPanel', {
314 ifname: me.ifname,
315 nodename: me.nodename,
316 dataCache: me.dataCache,
317 isCreate: me.isCreate
318 });
319
320 Ext.apply(me, {
321 subject: gettext('Network Device') + ' (veth)',
322 digest: me.dataCache.digest,
323 items: [ ipanel ]
324 });
325
326 me.callParent();
327 }
328 });
329
330 Ext.define('PVE.lxc.NetworkView', {
331 extend: 'Ext.grid.GridPanel',
332 alias: 'widget.pveLxcNetworkView',
333
334 onlineHelp: 'pct_container_network',
335
336 dataCache: {}, // used to store result of last load
337
338 stateful: true,
339 stateId: 'grid-lxc-network',
340
341 load: function() {
342 var me = this;
343
344 Proxmox.Utils.setErrorMask(me, true);
345
346 Proxmox.Utils.API2Request({
347 url: me.url,
348 failure: function(response, opts) {
349 Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus);
350 },
351 success: function(response, opts) {
352 Proxmox.Utils.setErrorMask(me, false);
353 var result = Ext.decode(response.responseText);
354 var data = result.data || {};
355 me.dataCache = data;
356 var records = [];
357 Ext.Object.each(data, function(key, value) {
358 if (!key.match(/^net\d+/)) {
359 return; // continue
360 }
361 var net = PVE.Parser.parseLxcNetwork(value);
362 net.id = key;
363 records.push(net);
364 });
365 me.store.loadData(records);
366 me.down('button[name=addButton]').setDisabled((records.length >= 10));
367 }
368 });
369 },
370
371 initComponent : function() {
372 var me = this;
373
374 var nodename = me.pveSelNode.data.node;
375 if (!nodename) {
376 throw "no node name specified";
377 }
378
379 var vmid = me.pveSelNode.data.vmid;
380 if (!vmid) {
381 throw "no VM ID specified";
382 }
383
384 var caps = Ext.state.Manager.get('GuiCap');
385
386 me.url = '/nodes/' + nodename + '/lxc/' + vmid + '/config';
387
388 var store = new Ext.data.Store({
389 model: 'pve-lxc-network',
390 sorters: [
391 {
392 property : 'id',
393 direction: 'ASC'
394 }
395 ]
396 });
397
398 var sm = Ext.create('Ext.selection.RowModel', {});
399
400 var remove_btn = new Proxmox.button.Button({
401 text: gettext('Remove'),
402 disabled: true,
403 selModel: sm,
404 enableFn: function(rec) {
405 return !!caps.vms['VM.Config.Network'];
406 },
407 confirmMsg: function (rec) {
408 return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
409 "'" + rec.data.id + "'");
410 },
411 handler: function(btn, event, rec) {
412 Proxmox.Utils.API2Request({
413 url: me.url,
414 waitMsgTarget: me,
415 method: 'PUT',
416 params: { 'delete': rec.data.id, digest: me.dataCache.digest },
417 callback: function() {
418 me.load();
419 },
420 failure: function (response, opts) {
421 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
422 }
423 });
424 }
425 });
426
427 var run_editor = function() {
428 var rec = sm.getSelection()[0];
429 if (!rec) {
430 return;
431 }
432
433 if (!caps.vms['VM.Config.Network']) {
434 return false;
435 }
436
437 var win = Ext.create('PVE.lxc.NetworkEdit', {
438 url: me.url,
439 nodename: nodename,
440 dataCache: me.dataCache,
441 ifname: rec.data.id
442 });
443 win.on('destroy', me.load, me);
444 win.show();
445 };
446
447 var edit_btn = new Proxmox.button.Button({
448 text: gettext('Edit'),
449 selModel: sm,
450 disabled: true,
451 enableFn: function(rec) {
452 if (!caps.vms['VM.Config.Network']) {
453 return false;
454 }
455 return true;
456 },
457 handler: run_editor
458 });
459
460 Ext.apply(me, {
461 store: store,
462 selModel: sm,
463 tbar: [
464 {
465 text: gettext('Add'),
466 name: 'addButton',
467 disabled: !caps.vms['VM.Config.Network'],
468 handler: function() {
469 var win = Ext.create('PVE.lxc.NetworkEdit', {
470 url: me.url,
471 nodename: nodename,
472 isCreate: true,
473 dataCache: me.dataCache
474 });
475 win.on('destroy', me.load, me);
476 win.show();
477 }
478 },
479 remove_btn,
480 edit_btn
481 ],
482 columns: [
483 {
484 header: 'ID',
485 width: 50,
486 dataIndex: 'id'
487 },
488 {
489 header: gettext('Name'),
490 width: 80,
491 dataIndex: 'name'
492 },
493 {
494 header: gettext('Bridge'),
495 width: 80,
496 dataIndex: 'bridge'
497 },
498 {
499 header: gettext('Firewall'),
500 width: 80,
501 dataIndex: 'firewall',
502 renderer: Proxmox.Utils.format_boolean
503 },
504 {
505 header: gettext('VLAN Tag'),
506 width: 80,
507 dataIndex: 'tag'
508 },
509 {
510 header: gettext('MAC address'),
511 width: 110,
512 dataIndex: 'hwaddr'
513 },
514 {
515 header: gettext('IP address'),
516 width: 150,
517 dataIndex: 'ip',
518 renderer: function(value, metaData, rec) {
519 if (rec.data.ip && rec.data.ip6) {
520 return rec.data.ip + "<br>" + rec.data.ip6;
521 } else if (rec.data.ip6) {
522 return rec.data.ip6;
523 } else {
524 return rec.data.ip;
525 }
526 }
527 },
528 {
529 header: gettext('Gateway'),
530 width: 150,
531 dataIndex: 'gw',
532 renderer: function(value, metaData, rec) {
533 if (rec.data.gw && rec.data.gw6) {
534 return rec.data.gw + "<br>" + rec.data.gw6;
535 } else if (rec.data.gw6) {
536 return rec.data.gw6;
537 } else {
538 return rec.data.gw;
539 }
540 }
541 }
542 ],
543 listeners: {
544 activate: me.load,
545 itemdblclick: run_editor
546 }
547 });
548
549 me.callParent();
550 }
551 }, function() {
552
553 Ext.define('pve-lxc-network', {
554 extend: "Ext.data.Model",
555 proxy: { type: 'memory' },
556 fields: [ 'id', 'name', 'hwaddr', 'bridge',
557 'ip', 'gw', 'ip6', 'gw6', 'tag', 'firewall' ]
558 });
559
560 });
561