]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/Network.js
ui: eslint: fix trailing comma and comma related whitespaces errors
[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 < 32; 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 return true;
116 },
117 },
118 {
119 xtype: 'textfield',
120 name: 'hwaddr',
121 fieldLabel: gettext('MAC address'),
122 vtype: 'MacAddress',
123 value: cdata.hwaddr,
124 allowBlank: true,
125 emptyText: 'auto',
126 },
127 {
128 xtype: 'PVE.form.BridgeSelector',
129 name: 'bridge',
130 nodename: me.nodename,
131 fieldLabel: gettext('Bridge'),
132 value: cdata.bridge,
133 allowBlank: false,
134 },
135 {
136 xtype: 'pveVlanField',
137 name: 'tag',
138 value: cdata.tag,
139 },
140 {
141 xtype: 'numberfield',
142 name: 'rate',
143 fieldLabel: gettext('Rate limit') + ' (MB/s)',
144 minValue: 0,
145 maxValue: 10*1024,
146 value: cdata.rate,
147 emptyText: 'unlimited',
148 allowBlank: true,
149 },
150 {
151 xtype: 'proxmoxcheckbox',
152 fieldLabel: gettext('Firewall'),
153 name: 'firewall',
154 value: cdata.firewall,
155 },
156 ];
157
158 var dhcp4 = (cdata.ip === 'dhcp');
159 if (dhcp4) {
160 cdata.ip = '';
161 cdata.gw = '';
162 }
163
164 var auto6 = (cdata.ip6 === 'auto');
165 var dhcp6 = (cdata.ip6 === 'dhcp');
166 if (auto6 || dhcp6) {
167 cdata.ip6 = '';
168 cdata.gw6 = '';
169 }
170
171 me.column2 = [
172 {
173 layout: {
174 type: 'hbox',
175 align: 'middle',
176 },
177 border: false,
178 margin: '0 0 5 0',
179 items: [
180 {
181 xtype: 'label',
182 text: 'IPv4:', // do not localize
183 },
184 {
185 xtype: 'radiofield',
186 boxLabel: gettext('Static'),
187 name: 'ipv4mode',
188 inputValue: 'static',
189 checked: !dhcp4,
190 margin: '0 0 0 10',
191 listeners: {
192 change: function(cb, value) {
193 me.down('field[name=ip]').setEmptyText(
194 !!value ? Proxmox.Utils.NoneText : "",
195 );
196 me.down('field[name=ip]').setDisabled(!value);
197 me.down('field[name=gw]').setDisabled(!value);
198 },
199 },
200 },
201 {
202 xtype: 'radiofield',
203 boxLabel: 'DHCP', // do not localize
204 name: 'ipv4mode',
205 inputValue: 'dhcp',
206 checked: dhcp4,
207 margin: '0 0 0 10',
208 },
209 ],
210 },
211 {
212 xtype: 'textfield',
213 name: 'ip',
214 vtype: 'IPCIDRAddress',
215 value: cdata.ip,
216 emptyText: dhcp4 ? '' : Proxmox.Utils.NoneText,
217 disabled: dhcp4,
218 fieldLabel: 'IPv4/CIDR', // do not localize
219 },
220 {
221 xtype: 'textfield',
222 name: 'gw',
223 value: cdata.gw,
224 vtype: 'IPAddress',
225 disabled: dhcp4,
226 fieldLabel: gettext('Gateway') + ' (IPv4)',
227 margin: '0 0 3 0', // override bottom margin to account for the menuseparator
228 },
229 {
230 xtype: 'menuseparator',
231 height: '3',
232 margin: '0',
233 },
234 {
235 layout: {
236 type: 'hbox',
237 align: 'middle',
238 },
239 border: false,
240 margin: '0 0 5 0',
241 items: [
242 {
243 xtype: 'label',
244 text: 'IPv6:', // do not localize
245 },
246 {
247 xtype: 'radiofield',
248 boxLabel: gettext('Static'),
249 name: 'ipv6mode',
250 inputValue: 'static',
251 checked: !(auto6 || dhcp6),
252 margin: '0 0 0 10',
253 listeners: {
254 change: function(cb, value) {
255 me.down('field[name=ip6]').setEmptyText(
256 !!value ? Proxmox.Utils.NoneText : "",
257 );
258 me.down('field[name=ip6]').setDisabled(!value);
259 me.down('field[name=gw6]').setDisabled(!value);
260 },
261 },
262 },
263 {
264 xtype: 'radiofield',
265 boxLabel: 'DHCP', // do not localize
266 name: 'ipv6mode',
267 inputValue: 'dhcp',
268 checked: dhcp6,
269 margin: '0 0 0 10',
270 },
271 {
272 xtype: 'radiofield',
273 boxLabel: 'SLAAC', // do not localize
274 name: 'ipv6mode',
275 inputValue: 'auto',
276 checked: auto6,
277 margin: '0 0 0 10',
278 },
279 ],
280 },
281 {
282 xtype: 'textfield',
283 name: 'ip6',
284 value: cdata.ip6,
285 emptyText: dhcp6 || auto6 ? '' : Proxmox.Utils.NoneText,
286 vtype: 'IP6CIDRAddress',
287 disabled: (dhcp6 || auto6),
288 fieldLabel: 'IPv6/CIDR', // do not localize
289 },
290 {
291 xtype: 'textfield',
292 name: 'gw6',
293 vtype: 'IP6Address',
294 value: cdata.gw6,
295 disabled: (dhcp6 || auto6),
296 fieldLabel: gettext('Gateway') + ' (IPv6)',
297 },
298 ];
299
300 me.callParent();
301 },
302 });
303
304 Ext.define('PVE.lxc.NetworkEdit', {
305 extend: 'Proxmox.window.Edit',
306
307 isAdd: true,
308
309 initComponent : function() {
310 var me = this;
311
312 if (!me.dataCache) {
313 throw "no dataCache specified";
314 }
315
316 if (!me.nodename) {
317 throw "no node name specified";
318 }
319
320 var ipanel = Ext.create('PVE.lxc.NetworkInputPanel', {
321 ifname: me.ifname,
322 nodename: me.nodename,
323 dataCache: me.dataCache,
324 isCreate: me.isCreate,
325 });
326
327 Ext.apply(me, {
328 subject: gettext('Network Device') + ' (veth)',
329 digest: me.dataCache.digest,
330 items: [ ipanel ],
331 });
332
333 me.callParent();
334 },
335 });
336
337 Ext.define('PVE.lxc.NetworkView', {
338 extend: 'Ext.grid.GridPanel',
339 alias: 'widget.pveLxcNetworkView',
340
341 onlineHelp: 'pct_container_network',
342
343 dataCache: {}, // used to store result of last load
344
345 stateful: true,
346 stateId: 'grid-lxc-network',
347
348 load: function() {
349 var me = this;
350
351 Proxmox.Utils.setErrorMask(me, true);
352
353 Proxmox.Utils.API2Request({
354 url: me.url,
355 failure: function(response, opts) {
356 Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus);
357 },
358 success: function(response, opts) {
359 Proxmox.Utils.setErrorMask(me, false);
360 var result = Ext.decode(response.responseText);
361 var data = result.data || {};
362 me.dataCache = data;
363 var records = [];
364 Ext.Object.each(data, function(key, value) {
365 if (!key.match(/^net\d+/)) {
366 return; // continue
367 }
368 var net = PVE.Parser.parseLxcNetwork(value);
369 net.id = key;
370 records.push(net);
371 });
372 me.store.loadData(records);
373 me.down('button[name=addButton]').setDisabled((records.length >= 32));
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 Proxmox.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 Proxmox.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 Proxmox.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
467 Ext.apply(me, {
468 store: store,
469 selModel: sm,
470 tbar: [
471 {
472 text: gettext('Add'),
473 name: 'addButton',
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 isCreate: 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: '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: Proxmox.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: {
551 activate: me.load,
552 itemdblclick: run_editor,
553 },
554 });
555
556 me.callParent();
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