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