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