]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/Pool.js
1 Ext
.define('PVE.CephPoolInputPanel', {
2 extend
: 'Proxmox.panel.InputPanel',
3 xtype
: 'pveCephPoolInputPanel',
4 mixins
: ['Proxmox.Mixin.CBind'],
7 onlineHelp
: 'pve_ceph_pools',
12 xtype
: 'pmxDisplayEditField',
13 fieldLabel
: gettext('Name'),
15 editable
: '{isCreate}',
22 xtype
: 'pmxDisplayEditField',
24 editable
: '{!isErasure}',
26 fieldLabel
: gettext('Size'),
29 xtype
: 'proxmoxintegerfield',
35 change: function(field
, val
) {
36 let size
= Math
.round(val
/ 2);
38 field
.up('inputpanel').down('field[name=min_size]').setValue(size
);
48 xtype
: 'proxmoxKVComboBox',
49 fieldLabel
: 'PG Autoscale Mode',
50 name
: 'pg_autoscale_mode',
56 value
: 'on', // FIXME: check ceph version and only default to on on octopus and newer
62 xtype
: 'proxmoxcheckbox',
63 fieldLabel
: gettext('Add as Storage'),
66 hidden
: '{!isCreate}',
72 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'),
78 xtype
: 'proxmoxintegerfield',
79 fieldLabel
: gettext('Min. Size'),
83 minValue
: (get) => get('isCreate') ? 2 : 1,
88 change: function(field
, minSize
) {
89 let panel
= field
.up('inputpanel');
90 let size
= panel
.down('field[name=size]').getValue();
92 let showWarning
= minSize
< (size
/ 2) && minSize
!== size
;
94 let fieldLabel
= gettext('Min. Size');
96 fieldLabel
= gettext('Min. Size') + ' <i class="fa fa-exclamation-triangle warning"></i>';
98 panel
.down('field[name=min_size-warning]').setHidden(!showWarning
);
99 field
.setFieldLabel(fieldLabel
);
104 xtype
: 'displayfield',
105 name
: 'min_size-warning',
107 value
: gettext('min_size < size/2 can lead to data loss, incomplete PGs or unfound objects.'),
111 xtype
: 'pmxDisplayEditField',
113 editable
: '{!isErasure}',
114 nodename
: '{nodename}',
115 isCreate
: '{isCreate}',
117 fieldLabel
: 'Crush Rule', // do not localize
120 xtype
: 'pveCephRuleSelector',
125 xtype
: 'proxmoxintegerfield',
126 fieldLabel
: '# of PGs',
137 xtype
: 'numberfield',
138 fieldLabel
: gettext('Target Ratio'),
139 name
: 'target_size_ratio',
146 'data-qtip': gettext('The ratio of storage amount this pool will consume compared to other pools with ratios. Used for auto-scaling.'),
150 xtype
: 'pveSizeField',
152 fieldLabel
: gettext('Target Size'),
161 'data-qtip': gettext('The amount of data eventually stored in this pool. Used for auto-scaling.'),
165 xtype
: 'displayfield',
167 value
: Ext
.String
.format(gettext('{0} takes precedence.'), gettext('Target Ratio')), // FIXME: tooltip?
170 xtype
: 'proxmoxintegerfield',
171 fieldLabel
: 'Min. # of PGs',
179 onGetValues: function(values
) {
180 Object
.keys(values
|| {}).forEach(function(name
) {
181 if (values
[name
] === '') {
190 Ext
.define('PVE.Ceph.PoolEdit', {
191 extend
: 'Proxmox.window.Edit',
192 alias
: 'widget.pveCephPoolEdit',
193 mixins
: ['Proxmox.Mixin.CBind'],
197 isCreate
: (cfg
) => !cfg
.pool_name
,
201 autoLoad
: get => !get('isCreate'),
202 url
: get => get('isCreate')
203 ? `/nodes/${get('nodename')}/ceph/pools`
204 : `/nodes/${get('nodename')}/ceph/pools/${get('pool_name')}`,
205 method
: get => get('isCreate') ? 'POST' : 'PUT',
210 subject
: gettext('Ceph Pool'),
213 xtype
: 'pveCephPoolInputPanel',
215 nodename
: '{nodename}',
216 pool_name
: '{pool_name}',
217 isErasure
: '{isErasure}',
218 isCreate
: '{isCreate}',
223 Ext
.define('PVE.node.Ceph.PoolList', {
224 extend
: 'Ext.grid.GridPanel',
225 alias
: 'widget.pveNodeCephPoolList',
227 onlineHelp
: 'chapter_pveceph',
230 stateId
: 'grid-ceph-pools',
231 bufferedRenderer
: false,
233 features
: [{ ftype
: 'summary' }],
237 text
: gettext('Name'),
241 dataIndex
: 'pool_name',
244 text
: gettext('Type'),
251 text
: gettext('Size') + '/min',
255 renderer
: (v
, meta
, rec
) => `${v}/${rec.data.min_size}`,
259 text
: '# of Placement Groups',
266 text
: gettext('Optimal # of PGs'),
270 dataIndex
: 'pg_num_final',
271 renderer: function(value
, metaData
) {
273 value
= '<i class="fa fa-info-circle faded"></i> n/a';
274 metaData
.tdAttr
= 'data-qtip="Needs pg_autoscaler module enabled."';
280 text
: gettext('Min. # of PGs'),
284 dataIndex
: 'pg_num_min',
288 text
: gettext('Target Ratio'),
292 dataIndex
: 'target_size_ratio',
293 renderer
: Ext
.util
.Format
.numberRenderer('0.0000'),
297 text
: gettext('Target Size'),
301 dataIndex
: 'target_size',
303 renderer: function(v
, metaData
, rec
) {
304 let value
= Proxmox
.Utils
.render_size(v
);
305 if (rec
.data
.target_size_ratio
> 0) {
306 value
= '<i class="fa fa-info-circle faded"></i> ' + value
;
307 metaData
.tdAttr
= 'data-qtip="Target Size Ratio takes precedence over Target Size."';
313 text
: gettext('Autoscale Mode'),
317 dataIndex
: 'pg_autoscale_mode',
320 text
: 'CRUSH Rule (ID)',
324 renderer
: (v
, meta
, rec
) => `${v} (${rec.data.crush_rule})`,
325 dataIndex
: 'crush_rule_name',
328 text
: gettext('Used') + ' (%)',
333 dataIndex
: 'bytes_used',
335 summaryRenderer
: Proxmox
.Utils
.render_size
,
336 renderer: function(v
, meta
, rec
) {
337 let percentage
= Ext
.util
.Format
.percent(rec
.data
.percent_used
, '0.00');
338 let used
= Proxmox
.Utils
.render_size(v
);
339 return `${used} (${percentage})`;
343 initComponent: function() {
346 var nodename
= me
.pveSelNode
.data
.node
;
348 throw "no node name specified";
351 var sm
= Ext
.create('Ext.selection.RowModel', {});
353 var rstore
= Ext
.create('Proxmox.data.UpdateStore', {
355 storeid
: 'ceph-pool-list' + nodename
,
356 model
: 'ceph-pool-list',
359 url
: `/api2/json/nodes/${nodename}/ceph/pools`,
362 let store
= Ext
.create('Proxmox.data.DiffStore', { rstore
: rstore
});
364 // manages the "install ceph?" overlay
365 PVE
.Utils
.monitor_ceph_installed(me
, rstore
, nodename
);
367 var run_editor = function() {
368 let rec
= sm
.getSelection()[0];
369 if (!rec
|| !rec
.data
.pool_name
) {
372 Ext
.create('PVE.Ceph.PoolEdit', {
373 title
: gettext('Edit') + ': Ceph Pool',
375 pool_name
: rec
.data
.pool_name
,
376 isErasure
: rec
.data
.type
=== 'erasure',
379 destroy
: () => rstore
.load(),
389 text
: gettext('Create'),
390 handler: function() {
391 Ext
.create('PVE.Ceph.PoolEdit', {
392 title
: gettext('Create') + ': Ceph Pool',
398 destroy
: () => rstore
.load(),
404 xtype
: 'proxmoxButton',
405 text
: gettext('Edit'),
411 xtype
: 'proxmoxButton',
412 text
: gettext('Destroy'),
415 handler: function() {
416 let rec
= sm
.getSelection()[0];
417 if (!rec
|| !rec
.data
.pool_name
) {
420 let poolName
= rec
.data
.pool_name
;
421 Ext
.create('Proxmox.window.SafeDestroy', {
423 url
: `/nodes/${nodename}/ceph/pools/${poolName}`,
431 taskName
: 'cephdestroypool',
434 destroy
: () => rstore
.load(),
441 activate
: () => rstore
.startUpdate(),
442 destroy
: () => rstore
.stopUpdate(),
443 itemdblclick
: run_editor
,
450 Ext
.define('ceph-pool-list', {
451 extend
: 'Ext.data.Model',
452 fields
: ['pool_name',
453 { name
: 'pool', type
: 'integer' },
454 { name
: 'size', type
: 'integer' },
455 { name
: 'min_size', type
: 'integer' },
456 { name
: 'pg_num', type
: 'integer' },
457 { name
: 'pg_num_min', type
: 'integer' },
458 { name
: 'bytes_used', type
: 'integer' },
459 { name
: 'percent_used', type
: 'number' },
460 { name
: 'crush_rule', type
: 'integer' },
461 { name
: 'crush_rule_name', type
: 'string' },
462 { name
: 'pg_autoscale_mode', type
: 'string' },
463 { name
: 'pg_num_final', type
: 'integer' },
464 { name
: 'target_size_ratio', type
: 'number' },
465 { name
: 'target_size', type
: 'integer' },
467 idProperty
: 'pool_name',
471 Ext
.define('PVE.form.CephRuleSelector', {
472 extend
: 'Ext.form.field.ComboBox',
473 alias
: 'widget.pveCephRuleSelector',
477 displayField
: 'name',
481 initComponent: function() {
485 throw "no nodename given";
493 url
: `/api2/json/nodes/${me.nodename}/ceph/rules`,
495 autoLoad
: me
.isCreate
? {
496 callback
: (records
, op
, success
) => {
497 if (success
&& records
.length
> 0) {
498 me
.select(records
[0]);