]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/ResourceEdit.js
fix breaking gui when trying to edit a bindmount rootfs
[pve-manager.git] / www / manager6 / lxc / ResourceEdit.js
1 /*jslint confusion: true */
2 var labelWidth = 120;
3
4 Ext.define('PVE.lxc.MemoryEdit', {
5 extend: 'PVE.window.Edit',
6
7 initComponent : function() {
8 var me = this;
9
10 Ext.apply(me, {
11 subject: gettext('Memory'),
12 items: Ext.create('PVE.lxc.MemoryInputPanel')
13 });
14
15 me.callParent();
16
17 me.load();
18 }
19 });
20
21
22 Ext.define('PVE.lxc.CPUEdit', {
23 extend: 'PVE.window.Edit',
24
25 initComponent : function() {
26 var me = this;
27
28 Ext.apply(me, {
29 subject: gettext('CPU'),
30 items: Ext.create('PVE.lxc.CPUInputPanel')
31 });
32
33 me.callParent();
34
35 me.load();
36 }
37 });
38
39 Ext.define('PVE.lxc.MountPointEdit', {
40 extend: 'PVE.window.Edit',
41
42 initComponent : function() {
43 var me = this;
44
45 var nodename = me.pveSelNode.data.node;
46 if (!nodename) {
47 throw "no node name specified";
48 }
49
50 var unused = me.confid && me.confid.match(/^unused\d+$/);
51
52 me.isCreate = me.confid ? unused : true;
53
54 var ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
55 confid: me.confid,
56 nodename: nodename,
57 unused: unused,
58 isCreate: me.isCreate
59 });
60
61 var subject;
62 if (unused) {
63 subject = gettext('Unused Disk');
64 } else if (me.isCreate) {
65 subject = gettext('Mount Point');
66 } else {
67 subject = gettext('Mount Point') + ' (' + me.confid + ')';
68 }
69
70 Ext.apply(me, {
71 subject: subject,
72 items: ipanel
73 });
74
75 me.callParent();
76
77 me.load({
78 success: function(response, options) {
79 ipanel.setVMConfig(response.result.data);
80 if (me.confid) {
81 var value = response.result.data[me.confid];
82 var mp = PVE.Parser.parseLxcMountPoint(value);
83
84 if (!mp) {
85 Ext.Msg.alert(gettext('Error'), 'Unable to parse mount point options');
86 me.close();
87 return;
88 }
89
90 ipanel.setMountPoint(mp);
91 me.isValid(); // trigger validation
92 }
93 }
94 });
95 }
96 });
97
98 Ext.define('PVE.lxc.CPUInputPanel', {
99 extend: 'PVE.panel.InputPanel',
100 alias: 'widget.pveLxcCPUInputPanel',
101
102 onlineHelp: 'pct_cpu',
103
104 insideWizard: false,
105
106 onGetValues: function(values) {
107 var me = this;
108
109 PVE.Utils.delete_if_default(values, 'cores', '', me.insideWizard);
110 // cpu{limit,unit} aren't in the wizard so create is always false
111 PVE.Utils.delete_if_default(values, 'cpulimit', '0', 0);
112 PVE.Utils.delete_if_default(values, 'cpuunits', '1024', 0);
113
114 return values;
115 },
116
117 initComponent : function() {
118 var me = this;
119
120 var column1 = [
121 {
122 xtype: 'pveIntegerField',
123 name: 'cores',
124 minValue: 1,
125 maxValue: 128,
126 value: me.insideWizard ? 1 : '',
127 fieldLabel: gettext('Cores'),
128 allowBlank: true,
129 emptyText: gettext('unlimited')
130 }
131 ];
132
133 var column2 = [
134 {
135 xtype: 'numberfield',
136 name: 'cpulimit',
137 minValue: 0,
138 value: '',
139 step: 1,
140 fieldLabel: gettext('CPU limit'),
141 labelWidth: labelWidth,
142 allowBlank: true,
143 emptyText: gettext('unlimited')
144 },
145 {
146 xtype: 'pveIntegerField',
147 name: 'cpuunits',
148 fieldLabel: gettext('CPU units'),
149 value: 1024,
150 minValue: 8,
151 maxValue: 500000,
152 labelWidth: labelWidth,
153 allowBlank: false
154 }
155 ];
156
157 if (me.insideWizard) {
158 me.column1 = column1;
159 } else {
160 me.column1 = column1;
161 me.column2 = column2;
162 }
163
164 me.callParent();
165 }
166 });
167
168 Ext.define('PVE.lxc.MemoryInputPanel', {
169 extend: 'PVE.panel.InputPanel',
170 alias: 'widget.pveLxcMemoryInputPanel',
171
172 onlineHelp: 'pct_memory',
173
174 insideWizard: false,
175
176 initComponent : function() {
177 var me = this;
178
179 var items = [
180 {
181 xtype: 'pveIntegerField',
182 name: 'memory',
183 minValue: 32,
184 maxValue: 512*1024,
185 value: '512',
186 step: 32,
187 fieldLabel: gettext('Memory') + ' (MB)',
188 labelWidth: labelWidth,
189 allowBlank: false
190 },
191 {
192 xtype: 'pveIntegerField',
193 name: 'swap',
194 minValue: 0,
195 maxValue: 128*1024,
196 value: '512',
197 step: 32,
198 fieldLabel: gettext('Swap') + ' (MB)',
199 labelWidth: labelWidth,
200 allowBlank: false
201 }
202 ];
203
204 if (me.insideWizard) {
205 me.column1 = items;
206 } else {
207 me.items = items;
208 }
209
210 me.callParent();
211 }
212 });
213
214 Ext.define('PVE.lxc.MountPointInputPanel', {
215 extend: 'PVE.panel.InputPanel',
216 alias: 'widget.pveLxcMountPointInputPanel',
217
218 insideWizard: false,
219
220 onlineHelp: 'pct_container_storage',
221
222 unused: false, // ADD usused disk imaged
223
224 vmconfig: {}, // used to select usused disks
225
226 onGetValues: function(values) {
227 var me = this;
228
229 var confid = me.confid || values.mpsel;
230
231 if (me.unused) {
232 me.mpdata.file = me.vmconfig[values.unusedId];
233 confid = values.mpsel;
234 } else if (me.isCreate) {
235 me.mpdata.file = values.storage + ':' + values.disksize;
236 }
237
238 if (confid !== 'rootfs') {
239 me.mpdata.mp = values.mp;
240 }
241
242 if (values.ro) {
243 me.mpdata.ro = 1;
244 } else {
245 delete me.mpdata.ro;
246 }
247
248 if (values.quota) {
249 me.mpdata.quota = 1;
250 } else {
251 delete me.mpdata.quota;
252 }
253
254 if (values.acl === 'Default') {
255 delete me.mpdata.acl;
256 } else {
257 me.mpdata.acl = values.acl;
258 }
259
260 if (values.backup) {
261 me.mpdata.backup = 1;
262 } else {
263 delete me.mpdata.backup;
264 }
265
266 if (values.noreplicate) {
267 me.mpdata.replicate = '0';
268 }
269 delete me.mpdata.noreplicate;
270
271 var res = {};
272 res[confid] = PVE.Parser.printLxcMountPoint(me.mpdata);
273 return res;
274 },
275
276 setMountPoint: function(mp) {
277 var me = this;
278
279 me.mpdata = mp;
280 if (!Ext.isDefined(me.mpdata.acl)) {
281 me.mpdata.acl = 'Default';
282 }
283
284 if (mp.type === 'bind') {
285 me.quota.setDisabled(true);
286 me.quota.setValue(false);
287 me.acl.setDisabled(true);
288 me.acl.setValue('Default');
289 me.hdstoragesel.setDisabled(true);
290 if (me.confid !== 'rootfs') {
291 me.backup.setDisabled(true);
292 }
293 }
294
295 if (mp.replicate) { // check box reverses the config option
296 mp.noreplicate = !PVE.Parser.parseBoolean(mp.replicate, 1);
297 delete mp.replicate;
298 }
299
300 me.setValues(mp);
301 },
302
303 setVMConfig: function(vmconfig) {
304 var me = this;
305
306 me.vmconfig = vmconfig;
307
308 if (me.mpsel) {
309 var i;
310 for (i = 0; i != 8; ++i) {
311 var name = "mp" + i;
312 if (!Ext.isDefined(vmconfig[name])) {
313 me.mpsel.setValue(name);
314 break;
315 }
316 }
317 }
318
319 if (me.unusedDisks) {
320 var disklist = [];
321 Ext.Object.each(vmconfig, function(key, value) {
322 if (key.match(/^unused\d+$/)) {
323 disklist.push([key, value]);
324 }
325 });
326 me.unusedDisks.store.loadData(disklist);
327 me.unusedDisks.setValue(me.confid);
328 }
329 },
330
331 setNodename: function(nodename) {
332 var me = this;
333 me.hdstoragesel.setNodename(nodename);
334 me.hdfilesel.setStorage(undefined, nodename);
335 },
336
337 initComponent : function() {
338 var me = this;
339
340 var isroot = me.confid === 'rootfs';
341
342 me.mpdata = {};
343
344 me.column1 = [];
345
346 if (!me.confid || me.unused) {
347 var names = [];
348 var i;
349 for (i = 0; i != 8; ++i) {
350 var name = 'mp' + i;
351 names.push([name, name]);
352 }
353 me.mpsel = Ext.create('PVE.form.KVComboBox', {
354 name: 'mpsel',
355 fieldLabel: gettext('Mount Point'),
356 matchFieldWidth: false,
357 allowBlank: false,
358 comboItems: names,
359 validator: function(value) {
360 if (!me.rendered) {
361 return;
362 }
363 if (Ext.isDefined(me.vmconfig[value])) {
364 return "Mount point is already in use.";
365 }
366 return true;
367 },
368 listeners: {
369 change: function(field, value) {
370 field.validate();
371 }
372 }
373 });
374 me.column1.push(me.mpsel);
375 }
376
377 // we always have this around, but only visible when creating a new mp
378 // since this handles per-filesystem capabilities
379 me.hdstoragesel = Ext.create('PVE.form.StorageSelector', {
380 name: 'storage',
381 nodename: me.nodename,
382 fieldLabel: gettext('Storage'),
383 storageContent: 'rootdir',
384 allowBlank: false,
385 autoSelect: true,
386 hidden: me.unused || !me.isCreate,
387 listeners: {
388 change: function(f, value) {
389 if (!value) { // initial store loading fires an unwanted 'change'
390 return;
391 }
392 if (me.mpdata.type === 'bind') {
393 me.quota.setDisabled(true);
394 me.quota.setValue(false);
395 me.acl.setDisabled(true);
396 me.acl.setValue('Default');
397 if (!isroot) {
398 me.backup.setDisabled(true);
399 }
400 return;
401 }
402 var rec = f.store.getById(value);
403 if (rec.data.type === 'zfs' ||
404 rec.data.type === 'zfspool') {
405 me.quota.setDisabled(true);
406 me.quota.setValue(false);
407 } else {
408 me.quota.setDisabled(false);
409 }
410 if (me.unused || !me.isCreate) {
411 return;
412 }
413 if (rec.data.type === 'iscsi') {
414 me.hdfilesel.setStorage(value);
415 me.hdfilesel.setDisabled(false);
416 me.hdfilesel.setVisible(true);
417 me.hdsizesel.setDisabled(true);
418 me.hdsizesel.setVisible(false);
419 } else if (rec.data.type === 'lvm' ||
420 rec.data.type === 'lvmthin' ||
421 rec.data.type === 'rbd' ||
422 rec.data.type === 'sheepdog' ||
423 rec.data.type === 'zfs' ||
424 rec.data.type === 'zfspool') {
425 me.hdfilesel.setDisabled(true);
426 me.hdfilesel.setVisible(false);
427 me.hdsizesel.setDisabled(false);
428 me.hdsizesel.setVisible(true);
429 } else {
430 me.hdfilesel.setDisabled(true);
431 me.hdfilesel.setVisible(false);
432 me.hdsizesel.setDisabled(false);
433 me.hdsizesel.setVisible(true);
434 }
435 }
436 }
437 });
438 me.column1.push(me.hdstoragesel);
439
440 if (me.unused) {
441 me.unusedDisks = Ext.create('PVE.form.KVComboBox', {
442 name: 'unusedId',
443 fieldLabel: gettext('Disk image'),
444 matchFieldWidth: false,
445 listConfig: {
446 width: 350
447 },
448 data: [],
449 allowBlank: false,
450 listeners: {
451 change: function(f, value) {
452 // make sure our buttons are enabled/disabled when switching
453 // between images on different storages:
454 var disk = me.vmconfig[value];
455 var storage = disk.split(':')[0];
456 me.hdstoragesel.setValue(storage);
457 }
458 }
459 });
460 me.column1.push(me.unusedDisks);
461 } else if (me.isCreate) {
462 me.hdfilesel = Ext.create('PVE.form.FileSelector', {
463 name: 'file',
464 nodename: me.nodename,
465 storageContent: 'images',
466 fieldLabel: gettext('Disk image'),
467 disabled: true,
468 hidden: true,
469 allowBlank: false
470 });
471 me.hdsizesel = Ext.createWidget('numberfield', {
472 name: 'disksize',
473 minValue: 0.1,
474 maxValue: 128*1024,
475 decimalPrecision: 3,
476 value: '8',
477 step: 1,
478 fieldLabel: gettext('Disk size') + ' (GB)',
479 allowBlank: false
480 });
481 me.column1.push(me.hdfilesel);
482 me.column1.push(me.hdsizesel);
483 } else {
484 me.column1.push({
485 xtype: 'textfield',
486 disabled: true,
487 submitValue: false,
488 fieldLabel: gettext('Disk image'),
489 name: 'file'
490 });
491 }
492
493 me.acl = Ext.createWidget('pveKVComboBox', {
494 name: 'acl',
495 fieldLabel: gettext('ACLs'),
496 comboItems: [['Default', 'Default'], ['1', 'On'], ['0', 'Off']],
497 value: 'Default',
498 allowBlank: true
499 });
500
501 me.quota = Ext.createWidget('pvecheckbox', {
502 name: 'quota',
503 defaultValue: 0,
504 fieldLabel: gettext('Enable quota')
505 });
506
507 me.column2 = [
508 me.acl,
509 me.quota
510 ];
511
512 if (!isroot) {
513 me.column2.splice(1, 0, {
514 xtype: 'pvecheckbox',
515 name: 'ro',
516 defaultValue: 0,
517 fieldLabel: gettext('Read-only'),
518 hidden: me.insideWizard
519 });
520
521 me.backup = Ext.createWidget('pvecheckbox',{
522 xtype: 'pvecheckbox',
523 name: 'backup',
524 fieldLabel: gettext('Backup')
525 });
526 if (me.mpdata.type !== 'bind') {
527 me.column2.push(me.backup);
528 }
529 me.column2.push({
530 xtype: 'pvecheckbox',
531 name: 'noreplicate',
532 fieldLabel: gettext('Skip replication')
533 });
534 me.column2.push({
535 xtype: 'textfield',
536 name: 'mp',
537 value: '',
538 emptyText: gettext('/some/path'),
539 allowBlank: false,
540 hidden: isroot,
541 fieldLabel: gettext('Path')
542 });
543 }
544
545 me.callParent();
546 }
547 });