]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/lxc/MPEdit.js
ui: lxc: switch reboot and stop button to match VMs
[pve-manager.git] / www / manager6 / lxc / MPEdit.js
CommitLineData
34c235be
DC
1/*jslint confusion: true*/
2/* hidden: boolean and string
3 * bind: function and object
4 * disabled: boolean and string
5 */
342225bf 6Ext.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
319Ext.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});