]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/lxc/MPEdit.js
ui: lxc/Mountpoints: eslint fixes and code cleanup/refactoring/modernize
[pve-manager.git] / www / manager6 / lxc / MPEdit.js
1 Ext.define('PVE.lxc.MountPointInputPanel', {
2 extend: 'Proxmox.panel.InputPanel',
3 xtype: 'pveLxcMountPointInputPanel',
4
5 onlineHelp: 'pct_container_storage',
6
7 insideWizard: false,
8
9 unused: false, // add unused disk imaged
10 unprivileged: false,
11
12 vmconfig: {}, // used to select unused disks
13
14 setUnprivileged: function(unprivileged) {
15 var me = this;
16 var vm = me.getViewModel();
17 me.unprivileged = unprivileged;
18 vm.set('unpriv', unprivileged);
19 },
20
21 onGetValues: function(values) {
22 var me = this;
23
24 var confid = me.confid || "mp"+values.mpid;
25 me.mp.file = me.down('field[name=file]').getValue();
26
27 if (me.unused) {
28 confid = "mp"+values.mpid;
29 } else if (me.isCreate) {
30 me.mp.file = values.hdstorage + ':' + values.disksize;
31 }
32
33 // delete unnecessary fields
34 delete values.mpid;
35 delete values.hdstorage;
36 delete values.disksize;
37 delete values.diskformat;
38
39 let setMPOpt = (k, src, v) => PVE.Utils.propertyStringSet(me.mp, src, k, v);
40
41 setMPOpt('mp', values.mp);
42 let mountOpts = (values.mountoptions || []).join(';');
43 setMPOpt('mountoptions', values.mountoptions, mountOpts);
44 setMPOpt('mp', values.mp);
45 setMPOpt('backup', values.backup);
46 setMPOpt('quota', values.quota);
47 setMPOpt('ro', values.ro);
48 setMPOpt('acl', values.acl);
49 setMPOpt('replicate', values.replicate);
50
51 let res = {};
52 res[confid] = PVE.Parser.printLxcMountPoint(me.mp);
53 return res;
54 },
55
56 setMountPoint: function(mp) {
57 let me = this;
58 let vm = me.getViewModel();
59 vm.set('mptype', mp.type);
60 if (mp.mountoptions) {
61 mp.mountoptions = mp.mountoptions.split(';');
62 }
63 me.mp = mp;
64 me.filterMountOptions();
65 me.setValues(mp);
66 },
67
68 filterMountOptions: function() {
69 let me = this;
70 if (me.confid === 'rootfs') {
71 let field = me.down('field[name=mountoptions]');
72 let exclude = ['nodev', 'noexec'];
73 let filtered = field.comboItems.filter(v => !exclude.includes(v[0]));
74 field.setComboItems(filtered);
75 }
76 },
77
78 setVMConfig: function(vmconfig) {
79 let me = this;
80 let vm = me.getViewModel();
81 me.vmconfig = vmconfig;
82 vm.set('unpriv', vmconfig.unprivileged);
83
84 PVE.Utils.forEachMP((bus, i) => {
85 let name = "mp" + i.toString();
86 if (!Ext.isDefined(vmconfig[name])) {
87 me.down('field[name=mpid]').setValue(i);
88 return false;
89 }
90 return undefined;
91 });
92 },
93
94 setNodename: function(nodename) {
95 let me = this;
96 let vm = me.getViewModel();
97 vm.set('node', nodename);
98 me.down('#diskstorage').setNodename(nodename);
99 },
100
101 controller: {
102 xclass: 'Ext.app.ViewController',
103
104 control: {
105 'field[name=mpid]': {
106 change: function(field, value) {
107 field.validate();
108 },
109 },
110 '#hdstorage': {
111 change: function(field, newValue) {
112 let me = this;
113 if (!newValue) {
114 return;
115 }
116
117 let rec = field.store.getById(newValue);
118 if (!rec) {
119 return;
120 }
121 me.getViewModel().set('type', rec.data.type);
122 },
123 },
124 },
125 init: function(view) {
126 let me = this;
127 let vm = this.getViewModel();
128 view.mp = {};
129 vm.set('confid', view.confid);
130 vm.set('unused', view.unused);
131 vm.set('node', view.nodename);
132 vm.set('unpriv', view.unprivileged);
133 vm.set('hideStorSelector', view.unused || !view.isCreate);
134
135 if (view.isCreate) { // can be array if created from unused disk
136 vm.set('isIncludedInBackup', true);
137 if (view.insideWizard) {
138 view.filterMountOptions();
139 }
140 }
141 },
142 },
143
144 viewModel: {
145 data: {
146 unpriv: false,
147 unused: false,
148 showStorageSelector: false,
149 mptype: '',
150 type: '',
151 confid: '',
152 node: '',
153 },
154
155 formulas: {
156 quota: function(get) {
157 return !(get('type') === 'zfs' ||
158 get('type') === 'zfspool' ||
159 get('unpriv') ||
160 get('isBind'));
161 },
162 hasMP: function(get) {
163 return !!get('confid') && !get('unused');
164 },
165 isRoot: function(get) {
166 return get('confid') === 'rootfs';
167 },
168 isBind: function(get) {
169 return get('mptype') === 'bind';
170 },
171 isBindOrRoot: function(get) {
172 return get('isBind') || get('isRoot');
173 },
174 },
175 },
176
177 column1: [
178 {
179 xtype: 'proxmoxintegerfield',
180 name: 'mpid',
181 fieldLabel: gettext('Mount Point ID'),
182 minValue: 0,
183 maxValue: PVE.Utils.mp_counts.mps - 1,
184 hidden: true,
185 allowBlank: false,
186 disabled: true,
187 bind: {
188 hidden: '{hasMP}',
189 disabled: '{hasMP}',
190 },
191 validator: function(value) {
192 let view = this.up('inputpanel');
193 if (!view.rendered) {
194 return undefined;
195 }
196 if (Ext.isDefined(view.vmconfig["mp"+value])) {
197 return "Mount point is already in use.";
198 }
199 return true;
200 },
201 },
202 {
203 xtype: 'pveDiskStorageSelector',
204 itemId: 'diskstorage',
205 storageContent: 'rootdir',
206 hidden: true,
207 autoSelect: true,
208 selectformat: false,
209 defaultSize: 8,
210 bind: {
211 hidden: '{hideStorSelector}',
212 disabled: '{hideStorSelector}',
213 nodename: '{node}',
214 },
215 },
216 {
217 xtype: 'textfield',
218 disabled: true,
219 submitValue: false,
220 fieldLabel: gettext('Disk image'),
221 name: 'file',
222 bind: {
223 hidden: '{!hideStorSelector}',
224 },
225 },
226 ],
227
228 column2: [
229 {
230 xtype: 'textfield',
231 name: 'mp',
232 value: '',
233 emptyText: gettext('/some/path'),
234 allowBlank: false,
235 disabled: true,
236 fieldLabel: gettext('Path'),
237 bind: {
238 hidden: '{isRoot}',
239 disabled: '{isRoot}',
240 },
241 },
242 {
243 xtype: 'proxmoxcheckbox',
244 name: 'backup',
245 fieldLabel: gettext('Backup'),
246 autoEl: {
247 tag: 'div',
248 'data-qtip': gettext('Include volume in backup job'),
249 },
250 bind: {
251 hidden: '{isRoot}',
252 disabled: '{isBindOrRoot}',
253 value: '{isIncludedInBackup}',
254 },
255 },
256 ],
257
258 advancedColumn1: [
259 {
260 xtype: 'proxmoxcheckbox',
261 name: 'quota',
262 defaultValue: 0,
263 bind: {
264 disabled: '{!quota}',
265 },
266 fieldLabel: gettext('Enable quota'),
267 listeners: {
268 disable: function() {
269 this.reset();
270 },
271 },
272 },
273 {
274 xtype: 'proxmoxcheckbox',
275 name: 'ro',
276 defaultValue: 0,
277 bind: {
278 hidden: '{isRoot}',
279 disabled: '{isRoot}',
280 },
281 fieldLabel: gettext('Read-only'),
282 },
283 {
284 xtype: 'proxmoxKVComboBox',
285 name: 'mountoptions',
286 fieldLabel: gettext('Mount options'),
287 deleteEmpty: false,
288 comboItems: [
289 ['noatime', 'noatime'],
290 ['nodev', 'nodev'],
291 ['noexec', 'noexec'],
292 ['nosuid', 'nosuid'],
293 ],
294 multiSelect: true,
295 value: [],
296 allowBlank: true,
297 },
298 ],
299
300 advancedColumn2: [
301 {
302 xtype: 'proxmoxKVComboBox',
303 name: 'acl',
304 fieldLabel: 'ACLs',
305 deleteEmpty: false,
306 comboItems: [
307 ['__default__', Proxmox.Utils.defaultText],
308 ['1', Proxmox.Utils.enabledText],
309 ['0', Proxmox.Utils.disabledText],
310 ],
311 value: '__default__',
312 bind: {
313 disabled: '{isBind}',
314 },
315 allowBlank: true,
316 },
317 {
318 xtype: 'proxmoxcheckbox',
319 inputValue: '0', // reverses the logic
320 name: 'replicate',
321 fieldLabel: gettext('Skip replication'),
322 },
323 ],
324 });
325
326 Ext.define('PVE.lxc.MountPointEdit', {
327 extend: 'Proxmox.window.Edit',
328
329 unprivileged: false,
330
331 initComponent: function() {
332 let me = this;
333
334 let nodename = me.pveSelNode.data.node;
335 if (!nodename) {
336 throw "no node name specified";
337 }
338
339 let unused = me.confid && me.confid.match(/^unused\d+$/);
340
341 me.isCreate = me.confid ? unused : true;
342
343 let ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
344 confid: me.confid,
345 nodename: nodename,
346 unused: unused,
347 unprivileged: me.unprivileged,
348 isCreate: me.isCreate,
349 });
350
351 let subject;
352 if (unused) {
353 subject = gettext('Unused Disk');
354 } else if (me.isCreate) {
355 subject = gettext('Mount Point');
356 } else {
357 subject = gettext('Mount Point') + ' (' + me.confid + ')';
358 }
359
360 Ext.apply(me, {
361 subject: subject,
362 defaultFocus: me.confid !== 'rootfs' ? 'textfield[name=mp]' : 'tool',
363 items: ipanel,
364 });
365
366 me.callParent();
367
368 me.load({
369 success: function(response, options) {
370 ipanel.setVMConfig(response.result.data);
371
372 if (me.confid) {
373 let value = response.result.data[me.confid];
374 let mp = PVE.Parser.parseLxcMountPoint(value);
375 if (!mp) {
376 Ext.Msg.alert(gettext('Error'), 'Unable to parse mount point options');
377 me.close();
378 return;
379 }
380 ipanel.setMountPoint(mp);
381 me.isValid(); // trigger validation
382 }
383 },
384 });
385 },
386 });