]>
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}',
17 disabled
: '{!isCreate}',
23 xtype
: 'proxmoxintegerfield',
24 fieldLabel
: gettext('Size'),
31 change: function(field
, val
) {
32 let size
= Math
.round(val
/ 2);
34 field
.up('inputpanel').down('field[name=min_size]').setValue(size
);
42 xtype
: 'proxmoxKVComboBox',
43 fieldLabel
: 'PG Autoscale Mode',
44 name
: 'pg_autoscale_mode',
56 xtype
: 'proxmoxcheckbox',
57 fieldLabel
: gettext('Add as Storage'),
60 hidden
: '{!isCreate}',
66 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'),
72 xtype
: 'proxmoxintegerfield',
73 fieldLabel
: gettext('Min. Size'),
77 minValue
: (get) => get('isCreate') ? 2 : 1,
82 change: function(field
, val
) {
84 let warn_text
= gettext('Min. Size');
88 warn_text
= gettext('Min. Size') + ' <i class="fa fa-exclamation-triangle warning"></i>';
91 field
.up().down('field[name=min_size-warning]').setHidden(warn
);
92 field
.setFieldLabel(warn_text
);
97 xtype
: 'displayfield',
98 name
: 'min_size-warning',
100 value
: 'A pool with min_size=1 could lead to data loss, incomplete PGs or unfound objects.',
104 xtype
: 'pveCephRuleSelector',
105 fieldLabel
: 'Crush Rule', // do not localize
106 cbind
: { nodename
: '{nodename}' },
111 xtype
: 'proxmoxintegerfield',
112 fieldLabel
: '# of PGs',
123 xtype
: 'numberfield',
124 fieldLabel
: gettext('Target Size Ratio'),
125 name
: 'target_size_ratio',
133 xtype
: 'numberfield',
134 fieldLabel
: gettext('Target Size') + ' (GiB)',
142 xtype
: 'displayfield',
144 value
: 'Target Size Ratio takes precedence.',
147 xtype
: 'proxmoxintegerfield',
148 fieldLabel
: 'Min. # of PGs',
157 onGetValues: function(values
) {
158 Object
.keys(values
|| {}).forEach(function(name
) {
159 if (values
[name
] === '') {
164 let target_size
= Number
.parseFloat(values
.target_size
);
166 if (Ext
.isNumber(target_size
) && target_size
!== 0) {
167 values
.target_size
= (target_size
*1024*1024*1024).toFixed(0);
173 setValues: function(values
) {
174 let target_size
= Number
.parseFloat(values
.target_size
);
176 if (Ext
.isNumber(target_size
) && target_size
!== 0) {
177 values
.target_size
= target_size
/1024/1024/1024;
180 this.callParent([values
]);
185 Ext
.define('PVE.CephPoolEdit', {
186 extend
: 'Proxmox.window.Edit',
187 alias
: 'widget.pveCephPoolEdit',
188 xtype
: 'pveCephPoolEdit',
189 mixins
: ['Proxmox.Mixin.CBind'],
193 isCreate
: (cfg
) => !cfg
.pool_name
,
197 autoLoad
: get => !get('isCreate'),
198 url
: get => get('isCreate')
199 ? `/nodes/${get('nodename')}/ceph/pools`
200 : `/nodes/${get('nodename')}/ceph/pools/${get('pool_name')}`,
201 method
: get => get('isCreate') ? 'POST' : 'PUT',
206 subject
: gettext('Ceph Pool'),
209 xtype
: 'pveCephPoolInputPanel',
211 nodename
: '{nodename}',
212 pool_name
: '{pool_name}',
213 isCreate
: '{isCreate}',
218 Ext
.define('PVE.node.CephPoolList', {
219 extend
: 'Ext.grid.GridPanel',
220 alias
: 'widget.pveNodeCephPoolList',
222 onlineHelp
: 'chapter_pveceph',
225 stateId
: 'grid-ceph-pools',
226 bufferedRenderer
: false,
228 features
: [{ ftype
: 'summary' }],
232 text
: gettext('Name'),
236 dataIndex
: 'pool_name',
239 text
: gettext('Size') + '/min',
243 renderer: function(v
, meta
, rec
) {
244 return v
+ '/' + rec
.data
.min_size
;
249 text
: '# of Placement Groups',
256 text
: gettext('Optimal # of PGs'),
260 dataIndex
: 'pg_num_final',
261 renderer: function(value
, metaData
) {
263 value
= '<i class="fa fa-info-circle faded"></i> n/a';
264 metaData
.tdAttr
= 'data-qtip="Needs pg_autoscaler module enabled."';
270 text
: gettext('Min. # of PGs'),
274 dataIndex
: 'pg_num_min',
278 text
: gettext('Target Size Ratio'),
282 dataIndex
: 'target_size_ratio',
283 renderer
: Ext
.util
.Format
.numberRenderer('0.0000'),
287 text
: gettext('Target Size'),
291 dataIndex
: 'target_size',
293 renderer: function(v
, metaData
, rec
) {
294 let value
= PVE
.Utils
.render_size(v
);
295 if (rec
.data
.target_size_ratio
> 0) {
296 value
= '<i class="fa fa-info-circle faded"></i> ' + value
;
297 metaData
.tdAttr
= 'data-qtip="Target Size Ratio takes precedence over Target Size."';
303 text
: gettext('Autoscale Mode'),
307 dataIndex
: 'pg_autoscale_mode',
310 text
: 'CRUSH Rule (ID)',
314 renderer: function(v
, meta
, rec
) {
315 return v
+ ' (' + rec
.data
.crush_rule
+ ')';
317 dataIndex
: 'crush_rule_name',
320 text
: gettext('Used') + ' (%)',
325 dataIndex
: 'bytes_used',
327 summaryRenderer
: PVE
.Utils
.render_size
,
328 renderer: function(v
, meta
, rec
) {
329 let percentage
= Ext
.util
.Format
.percent(rec
.data
.percent_used
, '0.00');
330 let used
= PVE
.Utils
.render_size(v
);
331 return used
+ ' (' + percentage
+ ')';
335 initComponent: function() {
338 var nodename
= me
.pveSelNode
.data
.node
;
340 throw "no node name specified";
343 var sm
= Ext
.create('Ext.selection.RowModel', {});
345 var rstore
= Ext
.create('Proxmox.data.UpdateStore', {
347 storeid
: 'ceph-pool-list' + nodename
,
348 model
: 'ceph-pool-list',
351 url
: "/api2/json/nodes/" + nodename
+ "/ceph/pools",
354 let store
= Ext
.create('Proxmox.data.DiffStore', { rstore
: rstore
});
356 PVE
.Utils
.handleStoreErrorOrMask(
359 /not (installed|initialized)/i,
362 PVE
.Utils
.showCephInstallOrMask(me
, error
.statusText
, nodename
, win
=> {
363 me
.mon(win
, 'cephInstallWindowClosed', () => rstore
.startUpdate());
368 var run_editor = function() {
369 let rec
= sm
.getSelection()[0];
370 if (!rec
|| !rec
.data
.pool_name
) {
373 Ext
.create('PVE.CephPoolEdit', {
374 title
: gettext('Edit') + ': Ceph Pool',
376 pool_name
: rec
.data
.pool_name
,
379 destroy
: () => rstore
.load(),
389 text
: gettext('Create'),
390 handler: function() {
391 Ext
.create('PVE.CephPoolEdit', {
392 title
: gettext('Create') + ': Ceph Pool',
397 destroy
: () => rstore
.load(),
403 xtype
: 'proxmoxButton',
404 text
: gettext('Edit'),
410 xtype
: 'proxmoxButton',
411 text
: gettext('Destroy'),
414 handler: function() {
415 let rec
= sm
.getSelection()[0];
416 if (!rec
|| !rec
.data
.pool_name
) {
419 let poolName
= rec
.data
.pool_name
;
420 Ext
.create('PVE.window.SafeDestroy', {
422 url
: `/nodes/${nodename}/ceph/pools/${poolName}`,
432 destroy
: () => rstore
.load(),
439 activate
: () => rstore
.startUpdate(),
440 destroy
: () => rstore
.stopUpdate(),
441 itemdblclick
: run_editor
,
448 Ext
.define('ceph-pool-list', {
449 extend
: 'Ext.data.Model',
450 fields
: ['pool_name',
451 { name
: 'pool', type
: 'integer' },
452 { name
: 'size', type
: 'integer' },
453 { name
: 'min_size', type
: 'integer' },
454 { name
: 'pg_num', type
: 'integer' },
455 { name
: 'pg_num_min', type
: 'integer' },
456 { name
: 'bytes_used', type
: 'integer' },
457 { name
: 'percent_used', type
: 'number' },
458 { name
: 'crush_rule', type
: 'integer' },
459 { name
: 'crush_rule_name', type
: 'string' },
460 { name
: 'pg_autoscale_mode', type
: 'string' },
461 { name
: 'pg_num_final', type
: 'integer' },
462 { name
: 'target_size_ratio', type
: 'number' },
463 { name
: 'target_size', type
: 'integer' },
465 idProperty
: 'pool_name',
469 Ext
.define('PVE.form.CephRuleSelector', {
470 extend
: 'Ext.form.field.ComboBox',
471 alias
: 'widget.pveCephRuleSelector',
475 displayField
: 'name',
479 initComponent: function() {
483 throw "no nodename given";
486 var store
= Ext
.create('Ext.data.Store', {
491 url
: `/api2/json/nodes/${me.nodename}/ceph/rules`,
502 callback: function(rec
, op
, success
) {
503 if (success
&& rec
.length
> 0) {