]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/lxc/MPEdit.js
{qemu, lxc}/Config: adapt to new proxmoxNodeTasks
[pve-manager.git] / www / manager6 / lxc / MPEdit.js
CommitLineData
342225bf 1Ext.define('PVE.lxc.MountPointInputPanel', {
ef4ef788 2 extend: 'Proxmox.panel.InputPanel',
34c235be 3 xtype: 'pveLxcMountPointInputPanel',
342225bf 4
342225bf
DC
5 onlineHelp: 'pct_container_storage',
6
7aaa492b 7 insideWizard: false,
342225bf 8
7aaa492b 9 unused: false, // add unused disk imaged
342225bf
DC
10 unprivileged: false,
11
12 vmconfig: {}, // used to select unused disks
13
658bf725 14 setUnprivileged: function(unprivileged) {
34c235be
DC
15 var me = this;
16 var vm = me.getViewModel();
17 me.unprivileged = unprivileged;
18 vm.set('unpriv', unprivileged);
658bf725
TL
19 },
20
342225bf
DC
21 onGetValues: function(values) {
22 var me = this;
23
85e6b368 24 var confid = me.confid || "mp"+values.mpid;
f9b63366 25 me.mp.file = me.down('field[name=file]').getValue();
342225bf
DC
26
27 if (me.unused) {
85e6b368 28 confid = "mp"+values.mpid;
342225bf 29 } else if (me.isCreate) {
f9b63366 30 me.mp.file = values.hdstorage + ':' + values.disksize;
342225bf
DC
31 }
32
34c235be 33 // delete unnecessary fields
85e6b368 34 delete values.mpid;
34c235be
DC
35 delete values.hdstorage;
36 delete values.disksize;
37 delete values.diskformat;
342225bf 38
7aaa492b
TL
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);
f9b63366 50
7aaa492b 51 let res = {};
f9b63366 52 res[confid] = PVE.Parser.printLxcMountPoint(me.mp);
342225bf
DC
53 return res;
54 },
55
56 setMountPoint: function(mp) {
7aaa492b
TL
57 let me = this;
58 let vm = me.getViewModel();
34c235be 59 vm.set('mptype', mp.type);
c115473d
OB
60 if (mp.mountoptions) {
61 mp.mountoptions = mp.mountoptions.split(';');
62 }
f9b63366 63 me.mp = mp;
7aaa492b
TL
64 me.filterMountOptions();
65 me.setValues(mp);
66 },
1780a644 67
7aaa492b
TL
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]));
1780a644
OB
74 field.setComboItems(filtered);
75 }
342225bf
DC
76 },
77
78 setVMConfig: function(vmconfig) {
7aaa492b
TL
79 let me = this;
80 let vm = me.getViewModel();
342225bf 81 me.vmconfig = vmconfig;
34c235be 82 vm.set('unpriv', vmconfig.unprivileged);
34c235be 83
7aaa492b
TL
84 PVE.Utils.forEachMP((bus, i) => {
85 let name = "mp" + i.toString();
34c235be 86 if (!Ext.isDefined(vmconfig[name])) {
85e6b368 87 me.down('field[name=mpid]').setValue(i);
34c235be 88 return false;
342225bf 89 }
7aaa492b 90 return undefined;
34c235be 91 });
342225bf
DC
92 },
93
94 setNodename: function(nodename) {
7aaa492b
TL
95 let me = this;
96 let vm = me.getViewModel();
34c235be 97 vm.set('node', nodename);
34c235be 98 me.down('#diskstorage').setNodename(nodename);
342225bf
DC
99 },
100
8058410f 101 controller: {
34c235be 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();
f6710aac 108 },
34c235be
DC
109 },
110 '#hdstorage': {
111 change: function(field, newValue) {
7aaa492b 112 let me = this;
34c235be 113 if (!newValue) {
342225bf
DC
114 return;
115 }
34c235be 116
7aaa492b 117 let rec = field.store.getById(newValue);
34c235be
DC
118 if (!rec) {
119 return;
342225bf 120 }
7aaa492b 121 me.getViewModel().set('type', rec.data.type);
f6710aac
TL
122 },
123 },
34c235be 124 },
34c235be 125 init: function(view) {
7aaa492b
TL
126 let me = this;
127 let vm = this.getViewModel();
f9b63366 128 view.mp = {};
34c235be
DC
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);
2b4c02c0 134
7aaa492b 135 if (view.isCreate) { // can be array if created from unused disk
2b4c02c0 136 vm.set('isIncludedInBackup', true);
7aaa492b
TL
137 if (view.insideWizard) {
138 view.filterMountOptions();
139 }
2b4c02c0 140 }
f6710aac 141 },
34c235be
DC
142 },
143
144 viewModel: {
145 data: {
146 unpriv: false,
147 unused: false,
148 showStorageSelector: false,
149 mptype: '',
150 type: '',
151 confid: '',
f6710aac 152 node: '',
34c235be
DC
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');
f6710aac
TL
173 },
174 },
34c235be 175 },
342225bf 176
34c235be
DC
177 column1: [
178 {
85e6b368
FG
179 xtype: 'proxmoxintegerfield',
180 name: 'mpid',
181 fieldLabel: gettext('Mount Point ID'),
182 minValue: 0,
183 maxValue: PVE.Utils.mp_counts.mps - 1,
34c235be
DC
184 hidden: true,
185 allowBlank: false,
6c442961 186 disabled: true,
34c235be
DC
187 bind: {
188 hidden: '{hasMP}',
f6710aac 189 disabled: '{hasMP}',
34c235be 190 },
34c235be 191 validator: function(value) {
46d9a35c
DJ
192 let view = this.up('inputpanel');
193 if (!view.rendered) {
7aaa492b 194 return undefined;
34c235be 195 }
46d9a35c 196 if (Ext.isDefined(view.vmconfig["mp"+value])) {
34c235be
DC
197 return "Mount point is already in use.";
198 }
34c235be 199 return true;
f6710aac 200 },
34c235be
DC
201 },
202 {
234d2e37 203 xtype: 'pveDiskStorageSelector',
34c235be 204 itemId: 'diskstorage',
342225bf 205 storageContent: 'rootdir',
34c235be 206 hidden: true,
342225bf 207 autoSelect: true,
34c235be 208 selectformat: false,
c6c8e2fc 209 defaultSize: 8,
34c235be
DC
210 bind: {
211 hidden: '{hideStorSelector}',
212 disabled: '{hideStorSelector}',
f6710aac
TL
213 nodename: '{node}',
214 },
34c235be
DC
215 },
216 {
217 xtype: 'textfield',
218 disabled: true,
219 submitValue: false,
220 fieldLabel: gettext('Disk image'),
221 name: 'file',
222 bind: {
f6710aac
TL
223 hidden: '{!hideStorSelector}',
224 },
225 },
34c235be
DC
226 ],
227
228 column2: [
229 {
230 xtype: 'textfield',
231 name: 'mp',
232 value: '',
8058410f 233 emptyText: gettext('/some/path'),
34c235be 234 allowBlank: false,
6c442961 235 disabled: true,
34c235be
DC
236 fieldLabel: gettext('Path'),
237 bind: {
238 hidden: '{isRoot}',
f6710aac
TL
239 disabled: '{isRoot}',
240 },
34c235be
DC
241 },
242 {
243 xtype: 'proxmoxcheckbox',
244 name: 'backup',
0bead056
TL
245 fieldLabel: gettext('Backup'),
246 autoEl: {
247 tag: 'div',
248 'data-qtip': gettext('Include volume in backup job'),
249 },
34c235be
DC
250 bind: {
251 hidden: '{isRoot}',
2b4c02c0 252 disabled: '{isBindOrRoot}',
f6710aac
TL
253 value: '{isIncludedInBackup}',
254 },
255 },
34c235be 256 ],
342225bf 257
34c235be
DC
258 advancedColumn1: [
259 {
260 xtype: 'proxmoxcheckbox',
342225bf
DC
261 name: 'quota',
262 defaultValue: 0,
34c235be 263 bind: {
f6710aac 264 disabled: '{!quota}',
34c235be 265 },
658bf725
TL
266 fieldLabel: gettext('Enable quota'),
267 listeners: {
268 disable: function() {
269 this.reset();
f6710aac
TL
270 },
271 },
34c235be
DC
272 },
273 {
274 xtype: 'proxmoxcheckbox',
275 name: 'ro',
276 defaultValue: 0,
277 bind: {
278 hidden: '{isRoot}',
f6710aac 279 disabled: '{isRoot}',
34c235be 280 },
f6710aac 281 fieldLabel: gettext('Read-only'),
7b6c7881
TL
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'],
f6710aac 292 ['nosuid', 'nosuid'],
7b6c7881
TL
293 ],
294 multiSelect: true,
295 value: [],
f6710aac 296 allowBlank: true,
7b6c7881 297 },
34c235be 298 ],
342225bf 299
34c235be
DC
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],
f6710aac 309 ['0', Proxmox.Utils.disabledText],
34c235be
DC
310 ],
311 value: '__default__',
312 bind: {
f6710aac 313 disabled: '{isBind}',
34c235be 314 },
f6710aac 315 allowBlank: true,
34c235be
DC
316 },
317 {
318 xtype: 'proxmoxcheckbox',
319 inputValue: '0', // reverses the logic
320 name: 'replicate',
f6710aac
TL
321 fieldLabel: gettext('Skip replication'),
322 },
323 ],
342225bf
DC
324});
325
326Ext.define('PVE.lxc.MountPointEdit', {
9fccc702 327 extend: 'Proxmox.window.Edit',
342225bf
DC
328
329 unprivileged: false,
330
8058410f 331 initComponent: function() {
7aaa492b 332 let me = this;
342225bf 333
7aaa492b 334 let nodename = me.pveSelNode.data.node;
342225bf
DC
335 if (!nodename) {
336 throw "no node name specified";
337 }
338
7aaa492b 339 let unused = me.confid && me.confid.match(/^unused\d+$/);
342225bf
DC
340
341 me.isCreate = me.confid ? unused : true;
342
7aaa492b 343 let ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
342225bf
DC
344 confid: me.confid,
345 nodename: nodename,
346 unused: unused,
347 unprivileged: me.unprivileged,
f6710aac 348 isCreate: me.isCreate,
342225bf
DC
349 });
350
7aaa492b 351 let subject;
342225bf
DC
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,
dc683ca0 362 defaultFocus: me.confid !== 'rootfs' ? 'textfield[name=mp]' : 'tool',
f6710aac 363 items: ipanel,
342225bf
DC
364 });
365
366 me.callParent();
367
368 me.load({
369 success: function(response, options) {
370 ipanel.setVMConfig(response.result.data);
342225bf 371
7aaa492b
TL
372 if (me.confid) {
373 let value = response.result.data[me.confid];
374 let mp = PVE.Parser.parseLxcMountPoint(value);
342225bf
DC
375 if (!mp) {
376 Ext.Msg.alert(gettext('Error'), 'Unable to parse mount point options');
377 me.close();
378 return;
379 }
342225bf
DC
380 ipanel.setMountPoint(mp);
381 me.isValid(); // trigger validation
382 }
f6710aac 383 },
342225bf 384 });
f6710aac 385 },
342225bf 386});