]>
Commit | Line | Data |
---|---|---|
4618a869 AA |
1 | Ext.define('PVE.CephPoolInputPanel', { |
2 | extend: 'Proxmox.panel.InputPanel', | |
3 | xtype: 'pveCephPoolInputPanel', | |
4 | mixins: ['Proxmox.Mixin.CBind'], | |
024be9c7 | 5 | |
7244f4bf | 6 | showProgress: true, |
35085f4a | 7 | onlineHelp: 'pve_ceph_pools', |
7244f4bf | 8 | |
024be9c7 | 9 | subject: 'Ceph Pool', |
b555a412 AL |
10 | |
11 | defaultSize: undefined, | |
12 | defaultMinSize: undefined, | |
13 | ||
cfcb74ab AL |
14 | controller: { |
15 | xclass: 'Ext.app.ViewController', | |
16 | ||
17 | init: function(view) { | |
18 | let vm = this.getViewModel(); | |
19 | vm.set('size', Number(view.defaultSize)); | |
20 | vm.set('minSize', Number(view.defaultMinSize)); | |
21 | }, | |
22 | sizeChange: function(field, val) { | |
23 | let vm = this.getViewModel(); | |
24 | let minSize = Math.round(val / 2); | |
25 | if (minSize > 1) { | |
26 | vm.set('minSize', minSize); | |
27 | } | |
28 | vm.set('size', val); // bind does not work in a pmxDisplayEditField, update manually | |
29 | }, | |
30 | }, | |
31 | ||
32 | viewModel: { | |
33 | data: { | |
34 | minSize: null, | |
35 | size: null, | |
36 | }, | |
37 | formulas: { | |
38 | minSizeLabel: (get) => { | |
39 | if (get('showMinSizeOneWarning') || get('showMinSizeHalfWarning')) { | |
40 | return `${gettext('Min. Size')} <i class="fa fa-exclamation-triangle warning"></i>`; | |
41 | } | |
42 | return gettext('Min. Size'); | |
43 | }, | |
44 | showMinSizeOneWarning: (get) => get('minSize') === 1, | |
45 | showMinSizeHalfWarning: (get) => { | |
46 | let minSize = get('minSize'); | |
47 | let size = get('size'); | |
48 | if (minSize === 1) { | |
49 | return false; | |
50 | } | |
51 | return minSize < (size / 2) && minSize !== size; | |
52 | }, | |
53 | }, | |
54 | }, | |
55 | ||
4618a869 | 56 | column1: [ |
c449c89a | 57 | { |
4618a869 | 58 | xtype: 'pmxDisplayEditField', |
c449c89a | 59 | fieldLabel: gettext('Name'), |
4618a869 AA |
60 | cbind: { |
61 | editable: '{isCreate}', | |
62 | value: '{pool_name}', | |
4618a869 | 63 | }, |
c449c89a | 64 | name: 'name', |
f6710aac | 65 | allowBlank: false, |
c449c89a DC |
66 | }, |
67 | { | |
1a042025 AL |
68 | xtype: 'pmxDisplayEditField', |
69 | cbind: { | |
70 | editable: '{!isErasure}', | |
71 | }, | |
c449c89a DC |
72 | fieldLabel: gettext('Size'), |
73 | name: 'size', | |
1a042025 AL |
74 | editConfig: { |
75 | xtype: 'proxmoxintegerfield', | |
b555a412 AL |
76 | cbind: { |
77 | value: (get) => get('defaultSize'), | |
78 | }, | |
1a042025 AL |
79 | minValue: 2, |
80 | maxValue: 7, | |
81 | allowBlank: false, | |
82 | listeners: { | |
cfcb74ab | 83 | change: 'sizeChange', |
4618a869 AA |
84 | }, |
85 | }, | |
86 | }, | |
87 | ], | |
88 | column2: [ | |
89 | { | |
90 | xtype: 'proxmoxKVComboBox', | |
91 | fieldLabel: 'PG Autoscale Mode', | |
92 | name: 'pg_autoscale_mode', | |
93 | comboItems: [ | |
94 | ['warn', 'warn'], | |
95 | ['on', 'on'], | |
96 | ['off', 'off'], | |
97 | ], | |
5da1b6d0 | 98 | value: 'on', // FIXME: check ceph version and only default to on on octopus and newer |
4618a869 AA |
99 | allowBlank: false, |
100 | autoSelect: false, | |
101 | labelWidth: 140, | |
c449c89a | 102 | }, |
4618a869 AA |
103 | { |
104 | xtype: 'proxmoxcheckbox', | |
105 | fieldLabel: gettext('Add as Storage'), | |
106 | cbind: { | |
107 | value: '{isCreate}', | |
108 | hidden: '{!isCreate}', | |
109 | }, | |
110 | name: 'add_storages', | |
111 | labelWidth: 140, | |
112 | autoEl: { | |
113 | tag: 'div', | |
114 | 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'), | |
115 | }, | |
116 | }, | |
117 | ], | |
118 | advancedColumn1: [ | |
c449c89a | 119 | { |
bf96f60d | 120 | xtype: 'proxmoxintegerfield', |
cfcb74ab AL |
121 | bind: { |
122 | fieldLabel: '{minSizeLabel}', | |
123 | value: '{minSize}', | |
124 | }, | |
c449c89a | 125 | name: 'min_size', |
4618a869 | 126 | cbind: { |
b555a412 AL |
127 | value: (get) => get('defaultMinSize'), |
128 | minValue: (get) => { | |
129 | if (Number(get('defaultMinSize')) === 1) { | |
130 | return 1; | |
131 | } else { | |
132 | return get('isCreate') ? 2 : 1; | |
133 | } | |
134 | }, | |
4618a869 | 135 | }, |
eef1979c | 136 | maxValue: 7, |
f6710aac | 137 | allowBlank: false, |
4618a869 AA |
138 | }, |
139 | { | |
140 | xtype: 'displayfield', | |
cfcb74ab AL |
141 | bind: { |
142 | hidden: '{!showMinSizeHalfWarning}', | |
143 | }, | |
144 | hidden: true, | |
4618a869 | 145 | userCls: 'pmx-hint', |
7748b41f | 146 | value: gettext('min_size < size/2 can lead to data loss, incomplete PGs or unfound objects.'), |
cfcb74ab AL |
147 | }, |
148 | { | |
149 | xtype: 'displayfield', | |
150 | bind: { | |
151 | hidden: '{!showMinSizeOneWarning}', | |
152 | }, | |
4618a869 | 153 | hidden: true, |
cfcb74ab AL |
154 | userCls: 'pmx-hint', |
155 | value: gettext('a min_size of 1 is not recommended and can lead to data loss'), | |
c449c89a DC |
156 | }, |
157 | { | |
1a042025 | 158 | xtype: 'pmxDisplayEditField', |
cd99757b | 159 | cbind: { |
1a042025 | 160 | editable: '{!isErasure}', |
cd99757b TL |
161 | nodename: '{nodename}', |
162 | isCreate: '{isCreate}', | |
163 | }, | |
1a042025 AL |
164 | fieldLabel: 'Crush Rule', // do not localize |
165 | name: 'crush_rule', | |
166 | editConfig: { | |
167 | xtype: 'pveCephRuleSelector', | |
168 | allowBlank: false, | |
169 | }, | |
c449c89a DC |
170 | }, |
171 | { | |
bf96f60d | 172 | xtype: 'proxmoxintegerfield', |
4618a869 | 173 | fieldLabel: '# of PGs', |
c449c89a | 174 | name: 'pg_num', |
6ad70a2b | 175 | value: 128, |
4618a869 | 176 | minValue: 1, |
c449c89a | 177 | maxValue: 32768, |
4618a869 AA |
178 | allowBlank: false, |
179 | emptyText: 128, | |
180 | }, | |
181 | ], | |
182 | advancedColumn2: [ | |
183 | { | |
184 | xtype: 'numberfield', | |
4d7acd65 | 185 | fieldLabel: gettext('Target Ratio'), |
4618a869 | 186 | name: 'target_size_ratio', |
4618a869 AA |
187 | minValue: 0, |
188 | decimalPrecision: 3, | |
23b316a3 | 189 | allowBlank: true, |
4618a869 | 190 | emptyText: '0.0', |
4d7acd65 TL |
191 | autoEl: { |
192 | tag: 'div', | |
193 | 'data-qtip': gettext('The ratio of storage amount this pool will consume compared to other pools with ratios. Used for auto-scaling.'), | |
194 | }, | |
5947248f DC |
195 | }, |
196 | { | |
18a5845e | 197 | xtype: 'pveSizeField', |
4618a869 | 198 | name: 'target_size', |
4d7acd65 | 199 | fieldLabel: gettext('Target Size'), |
18a5845e | 200 | unit: 'GiB', |
4618a869 AA |
201 | minValue: 0, |
202 | allowBlank: true, | |
86a5da83 | 203 | allowZero: true, |
4618a869 | 204 | emptyText: '0', |
d7eb3e22 | 205 | emptyValue: 0, |
4d7acd65 TL |
206 | autoEl: { |
207 | tag: 'div', | |
208 | 'data-qtip': gettext('The amount of data eventually stored in this pool. Used for auto-scaling.'), | |
209 | }, | |
4618a869 AA |
210 | }, |
211 | { | |
212 | xtype: 'displayfield', | |
213 | userCls: 'pmx-hint', | |
4d7acd65 | 214 | value: Ext.String.format(gettext('{0} takes precedence.'), gettext('Target Ratio')), // FIXME: tooltip? |
f6710aac | 215 | }, |
ae793232 AA |
216 | { |
217 | xtype: 'proxmoxintegerfield', | |
218 | fieldLabel: 'Min. # of PGs', | |
219 | name: 'pg_num_min', | |
ae793232 AA |
220 | minValue: 0, |
221 | allowBlank: true, | |
222 | emptyText: '0', | |
223 | }, | |
c449c89a | 224 | ], |
024be9c7 | 225 | |
4618a869 AA |
226 | onGetValues: function(values) { |
227 | Object.keys(values || {}).forEach(function(name) { | |
228 | if (values[name] === '') { | |
229 | delete values[name]; | |
230 | } | |
231 | }); | |
232 | ||
4618a869 AA |
233 | return values; |
234 | }, | |
4618a869 AA |
235 | }); |
236 | ||
519d9f3f | 237 | Ext.define('PVE.Ceph.PoolEdit', { |
4618a869 AA |
238 | extend: 'Proxmox.window.Edit', |
239 | alias: 'widget.pveCephPoolEdit', | |
4618a869 AA |
240 | mixins: ['Proxmox.Mixin.CBind'], |
241 | ||
242 | cbindData: { | |
243 | pool_name: '', | |
244 | isCreate: (cfg) => !cfg.pool_name, | |
b555a412 AL |
245 | defaultSize: undefined, |
246 | defaultMinSize: undefined, | |
4618a869 AA |
247 | }, |
248 | ||
249 | cbind: { | |
250 | autoLoad: get => !get('isCreate'), | |
251 | url: get => get('isCreate') | |
b5bbcb4c AL |
252 | ? `/nodes/${get('nodename')}/ceph/pool` |
253 | : `/nodes/${get('nodename')}/ceph/pool/${get('pool_name')}`, | |
254 | loadUrl: get => `/nodes/${get('nodename')}/ceph/pool/${get('pool_name')}/status`, | |
4618a869 AA |
255 | method: get => get('isCreate') ? 'POST' : 'PUT', |
256 | }, | |
257 | ||
cc0734fc DC |
258 | showProgress: true, |
259 | ||
4618a869 AA |
260 | subject: gettext('Ceph Pool'), |
261 | ||
262 | items: [{ | |
263 | xtype: 'pveCephPoolInputPanel', | |
264 | cbind: { | |
265 | nodename: '{nodename}', | |
266 | pool_name: '{pool_name}', | |
1a042025 | 267 | isErasure: '{isErasure}', |
4618a869 | 268 | isCreate: '{isCreate}', |
b555a412 AL |
269 | defaultSize: '{defaultSize}', |
270 | defaultMinSize: '{defaultMinSize}', | |
4618a869 AA |
271 | }, |
272 | }], | |
024be9c7 DM |
273 | }); |
274 | ||
519d9f3f | 275 | Ext.define('PVE.node.Ceph.PoolList', { |
024be9c7 | 276 | extend: 'Ext.grid.GridPanel', |
9ad28182 | 277 | alias: 'widget.pveNodeCephPoolList', |
024be9c7 | 278 | |
ba93a9c6 | 279 | onlineHelp: 'chapter_pveceph', |
5b7b4b76 | 280 | |
361aafd0 DC |
281 | stateful: true, |
282 | stateId: 'grid-ceph-pools', | |
c449c89a | 283 | bufferedRenderer: false, |
5b7b4b76 | 284 | |
8058410f | 285 | features: [{ ftype: 'summary' }], |
5b7b4b76 | 286 | |
c449c89a | 287 | columns: [ |
79007cfc AL |
288 | { |
289 | text: gettext('Pool #'), | |
290 | minWidth: 70, | |
291 | flex: 1, | |
292 | align: 'right', | |
293 | sortable: true, | |
294 | dataIndex: 'pool', | |
295 | }, | |
c449c89a | 296 | { |
11ce9e1a AA |
297 | text: gettext('Name'), |
298 | minWidth: 120, | |
299 | flex: 2, | |
c449c89a | 300 | sortable: true, |
f6710aac | 301 | dataIndex: 'pool_name', |
c449c89a | 302 | }, |
a73f844d AL |
303 | { |
304 | text: gettext('Type'), | |
305 | minWidth: 100, | |
306 | flex: 1, | |
307 | dataIndex: 'type', | |
308 | hidden: true, | |
309 | }, | |
c449c89a | 310 | { |
11ce9e1a AA |
311 | text: gettext('Size') + '/min', |
312 | minWidth: 100, | |
313 | flex: 1, | |
5b7b4b76 | 314 | align: 'right', |
1bd7bcdb | 315 | renderer: (v, meta, rec) => `${v}/${rec.data.min_size}`, |
f6710aac | 316 | dataIndex: 'size', |
c449c89a DC |
317 | }, |
318 | { | |
11ce9e1a AA |
319 | text: '# of Placement Groups', |
320 | flex: 1, | |
0e0f861a | 321 | minWidth: 100, |
11ce9e1a AA |
322 | align: 'right', |
323 | dataIndex: 'pg_num', | |
c449c89a DC |
324 | }, |
325 | { | |
11ce9e1a AA |
326 | text: gettext('Optimal # of PGs'), |
327 | flex: 1, | |
0e0f861a | 328 | minWidth: 100, |
11ce9e1a AA |
329 | align: 'right', |
330 | dataIndex: 'pg_num_final', | |
331 | renderer: function(value, metaData) { | |
332 | if (!value) { | |
333 | value = '<i class="fa fa-info-circle faded"></i> n/a'; | |
334 | metaData.tdAttr = 'data-qtip="Needs pg_autoscaler module enabled."'; | |
335 | } | |
336 | return value; | |
337 | }, | |
c9508b5d | 338 | }, |
ae793232 AA |
339 | { |
340 | text: gettext('Min. # of PGs'), | |
341 | flex: 1, | |
0e0f861a | 342 | minWidth: 100, |
ae793232 AA |
343 | align: 'right', |
344 | dataIndex: 'pg_num_min', | |
345 | hidden: true, | |
346 | }, | |
c449c89a | 347 | { |
0e0f861a | 348 | text: gettext('Target Ratio'), |
11ce9e1a | 349 | flex: 1, |
0e0f861a | 350 | minWidth: 100, |
11ce9e1a AA |
351 | align: 'right', |
352 | dataIndex: 'target_size_ratio', | |
353 | renderer: Ext.util.Format.numberRenderer('0.0000'), | |
354 | hidden: true, | |
355 | }, | |
356 | { | |
357 | text: gettext('Target Size'), | |
358 | flex: 1, | |
0e0f861a | 359 | minWidth: 100, |
11ce9e1a AA |
360 | align: 'right', |
361 | dataIndex: 'target_size', | |
362 | hidden: true, | |
363 | renderer: function(v, metaData, rec) { | |
ad33cfd5 | 364 | let value = Proxmox.Utils.render_size(v); |
11ce9e1a AA |
365 | if (rec.data.target_size_ratio > 0) { |
366 | value = '<i class="fa fa-info-circle faded"></i> ' + value; | |
367 | metaData.tdAttr = 'data-qtip="Target Size Ratio takes precedence over Target Size."'; | |
368 | } | |
369 | return value; | |
370 | }, | |
371 | }, | |
372 | { | |
373 | text: gettext('Autoscale Mode'), | |
374 | flex: 1, | |
0e0f861a | 375 | minWidth: 100, |
11ce9e1a AA |
376 | align: 'right', |
377 | dataIndex: 'pg_autoscale_mode', | |
378 | }, | |
379 | { | |
380 | text: 'CRUSH Rule (ID)', | |
381 | flex: 1, | |
382 | align: 'right', | |
383 | minWidth: 150, | |
0e0f861a | 384 | renderer: (v, meta, rec) => `${v} (${rec.data.crush_rule})`, |
11ce9e1a AA |
385 | dataIndex: 'crush_rule_name', |
386 | }, | |
387 | { | |
388 | text: gettext('Used') + ' (%)', | |
389 | flex: 1, | |
0e0f861a | 390 | minWidth: 150, |
11ce9e1a AA |
391 | sortable: true, |
392 | align: 'right', | |
393 | dataIndex: 'bytes_used', | |
394 | summaryType: 'sum', | |
1bd7bcdb | 395 | summaryRenderer: Proxmox.Utils.render_size, |
11ce9e1a AA |
396 | renderer: function(v, meta, rec) { |
397 | let percentage = Ext.util.Format.percent(rec.data.percent_used, '0.00'); | |
1bd7bcdb DC |
398 | let used = Proxmox.Utils.render_size(v); |
399 | return `${used} (${percentage})`; | |
11ce9e1a | 400 | }, |
f6710aac | 401 | }, |
c449c89a | 402 | ], |
024be9c7 DM |
403 | initComponent: function() { |
404 | var me = this; | |
405 | ||
406 | var nodename = me.pveSelNode.data.node; | |
407 | if (!nodename) { | |
408 | throw "no node name specified"; | |
409 | } | |
410 | ||
411 | var sm = Ext.create('Ext.selection.RowModel', {}); | |
412 | ||
0c7c0d6b | 413 | var rstore = Ext.create('Proxmox.data.UpdateStore', { |
024be9c7 | 414 | interval: 3000, |
d5066d84 | 415 | storeid: 'ceph-pool-list' + nodename, |
024be9c7 DM |
416 | model: 'ceph-pool-list', |
417 | proxy: { | |
261bb633 | 418 | type: 'proxmox', |
b5bbcb4c | 419 | url: `/api2/json/nodes/${nodename}/ceph/pool`, |
f6710aac | 420 | }, |
024be9c7 | 421 | }); |
ec455ed0 TL |
422 | let store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore }); |
423 | ||
13786fb0 TL |
424 | // manages the "install ceph?" overlay |
425 | PVE.Utils.monitor_ceph_installed(me, rstore, nodename); | |
024be9c7 | 426 | |
4618a869 | 427 | var run_editor = function() { |
ec455ed0 TL |
428 | let rec = sm.getSelection()[0]; |
429 | if (!rec || !rec.data.pool_name) { | |
4618a869 AA |
430 | return; |
431 | } | |
519d9f3f | 432 | Ext.create('PVE.Ceph.PoolEdit', { |
4618a869 AA |
433 | title: gettext('Edit') + ': Ceph Pool', |
434 | nodename: nodename, | |
435 | pool_name: rec.data.pool_name, | |
1a042025 | 436 | isErasure: rec.data.type === 'erasure', |
ec455ed0 TL |
437 | autoShow: true, |
438 | listeners: { | |
439 | destroy: () => rstore.load(), | |
440 | }, | |
4618a869 | 441 | }); |
4618a869 AA |
442 | }; |
443 | ||
024be9c7 DM |
444 | Ext.apply(me, { |
445 | store: store, | |
446 | selModel: sm, | |
ec455ed0 TL |
447 | tbar: [ |
448 | { | |
449 | text: gettext('Create'), | |
450 | handler: function() { | |
b555a412 AL |
451 | let keys = [ |
452 | 'global:osd-pool-default-min-size', | |
453 | 'global:osd-pool-default-size', | |
454 | ]; | |
455 | let params = { | |
456 | 'config-keys': keys.join(';'), | |
457 | }; | |
458 | ||
459 | Proxmox.Utils.API2Request({ | |
460 | url: '/nodes/localhost/ceph/cfg/value', | |
461 | method: 'GET', | |
462 | params, | |
463 | waitMsgTarget: me.getView(), | |
464 | failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus), | |
465 | success: function({ result: { data } }) { | |
466 | let global = data.global; | |
467 | let defaultSize = global?.['osd-pool-default-size'] ?? 3; | |
468 | let defaultMinSize = global?.['osd-pool-default-min-size'] ?? 2; | |
469 | ||
470 | Ext.create('PVE.Ceph.PoolEdit', { | |
471 | title: gettext('Create') + ': Ceph Pool', | |
472 | isCreate: true, | |
473 | isErasure: false, | |
474 | defaultSize, | |
475 | defaultMinSize, | |
476 | nodename: nodename, | |
477 | autoShow: true, | |
478 | listeners: { | |
479 | destroy: () => rstore.load(), | |
480 | }, | |
481 | }); | |
ec455ed0 TL |
482 | }, |
483 | }); | |
484 | }, | |
485 | }, | |
486 | { | |
487 | xtype: 'proxmoxButton', | |
488 | text: gettext('Edit'), | |
489 | selModel: sm, | |
490 | disabled: true, | |
491 | handler: run_editor, | |
492 | }, | |
493 | { | |
494 | xtype: 'proxmoxButton', | |
495 | text: gettext('Destroy'), | |
496 | selModel: sm, | |
497 | disabled: true, | |
498 | handler: function() { | |
499 | let rec = sm.getSelection()[0]; | |
500 | if (!rec || !rec.data.pool_name) { | |
501 | return; | |
502 | } | |
503 | let poolName = rec.data.pool_name; | |
b9635c9b | 504 | Ext.create('Proxmox.window.SafeDestroy', { |
ec455ed0 | 505 | showProgress: true, |
b5bbcb4c | 506 | url: `/nodes/${nodename}/ceph/pool/${poolName}`, |
ec455ed0 TL |
507 | params: { |
508 | remove_storages: 1, | |
509 | }, | |
510 | item: { | |
511 | type: 'CephPool', | |
512 | id: poolName, | |
513 | }, | |
b9635c9b | 514 | taskName: 'cephdestroypool', |
ec455ed0 TL |
515 | autoShow: true, |
516 | listeners: { | |
517 | destroy: () => rstore.load(), | |
518 | }, | |
519 | }); | |
520 | }, | |
521 | }, | |
522 | ], | |
024be9c7 | 523 | listeners: { |
6386068d TL |
524 | activate: () => rstore.startUpdate(), |
525 | destroy: () => rstore.stopUpdate(), | |
4618a869 | 526 | itemdblclick: run_editor, |
f6710aac | 527 | }, |
024be9c7 DM |
528 | }); |
529 | ||
530 | me.callParent(); | |
f6710aac | 531 | }, |
024be9c7 | 532 | }, function() { |
024be9c7 DM |
533 | Ext.define('ceph-pool-list', { |
534 | extend: 'Ext.data.Model', | |
8058410f TL |
535 | fields: ['pool_name', |
536 | { name: 'pool', type: 'integer' }, | |
537 | { name: 'size', type: 'integer' }, | |
538 | { name: 'min_size', type: 'integer' }, | |
539 | { name: 'pg_num', type: 'integer' }, | |
ae793232 | 540 | { name: 'pg_num_min', type: 'integer' }, |
8058410f TL |
541 | { name: 'bytes_used', type: 'integer' }, |
542 | { name: 'percent_used', type: 'number' }, | |
543 | { name: 'crush_rule', type: 'integer' }, | |
544 | { name: 'crush_rule_name', type: 'string' }, | |
4618a869 AA |
545 | { name: 'pg_autoscale_mode', type: 'string' }, |
546 | { name: 'pg_num_final', type: 'integer' }, | |
547 | { name: 'target_size_ratio', type: 'number' }, | |
548 | { name: 'target_size', type: 'integer' }, | |
024be9c7 | 549 | ], |
f6710aac | 550 | idProperty: 'pool_name', |
024be9c7 DM |
551 | }); |
552 | }); | |
d2692b86 DC |
553 | |
554 | Ext.define('PVE.form.CephRuleSelector', { | |
555 | extend: 'Ext.form.field.ComboBox', | |
556 | alias: 'widget.pveCephRuleSelector', | |
557 | ||
558 | allowBlank: false, | |
559 | valueField: 'name', | |
560 | displayField: 'name', | |
561 | editable: false, | |
562 | queryMode: 'local', | |
563 | ||
564 | initComponent: function() { | |
cd99757b | 565 | let me = this; |
d2692b86 DC |
566 | |
567 | if (!me.nodename) { | |
568 | throw "no nodename given"; | |
569 | } | |
c2cdef89 DC |
570 | |
571 | me.originalAllowBlank = me.allowBlank; | |
572 | me.allowBlank = true; | |
573 | ||
d2692b86 | 574 | Ext.apply(me, { |
261bb633 TL |
575 | store: { |
576 | fields: ['name'], | |
577 | sorters: 'name', | |
578 | proxy: { | |
579 | type: 'proxmox', | |
580 | url: `/api2/json/nodes/${me.nodename}/ceph/rules`, | |
581 | }, | |
c2cdef89 | 582 | autoLoad: { |
261bb633 | 583 | callback: (records, op, success) => { |
c2cdef89 | 584 | if (me.isCreate && success && records.length > 0) { |
261bb633 TL |
585 | me.select(records[0]); |
586 | } | |
c2cdef89 DC |
587 | |
588 | me.allowBlank = me.originalAllowBlank; | |
589 | delete me.originalAllowBlank; | |
590 | me.validate(); | |
261bb633 | 591 | }, |
c2cdef89 | 592 | }, |
261bb633 | 593 | }, |
d2692b86 DC |
594 | }); |
595 | ||
596 | me.callParent(); | |
f6710aac | 597 | }, |
d2692b86 DC |
598 | |
599 | }); |