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