Ext.define('PVE.ceph.StatusDetail', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveCephStatusDetail',
layout: {
type: 'hbox',
align: 'stretch'
},
bodyPadding: '0 5',
defaults: {
xtype: 'box',
style: {
'text-align':'center'
}
},
items: [{
flex: 1,
itemId: 'osds',
maxHeight: 250,
scrollable: true,
padding: '0 10 5 10',
data: {
total: 0,
upin: 0,
upout: 0,
downin: 0,
downout: 0,
oldosds: []
},
tpl: [
'
' + 'OSDs' + '
',
'',
' | ',
'',
gettext('In'),
' | ',
'',
gettext('Out'),
' | ',
'
',
'',
'',
gettext('Up'),
' | ',
'{upin} | ',
'{upout} | ',
'
',
'',
'',
gettext('Down'),
' | ',
'{downin} | ',
'{downout} | ',
'
',
'
',
'
',
gettext('Total'),
': {total}',
'
',
'',
' ' + gettext('Outdated OSDs') + "
",
'',
'
',
'osd.{id}:
',
'{version}
',
'',
'',
'
',
''
]
},
{
flex: 1,
border: false,
itemId: 'pgchart',
xtype: 'polar',
height: 184,
innerPadding: 5,
insetPadding: 5,
colors: [
'#CFCFCF',
'#21BF4B',
'#FFCC00',
'#FF6C59'
],
store: { },
series: [
{
type: 'pie',
donut: 60,
angleField: 'count',
tooltip: {
trackMouse: true,
renderer: function(tooltip, record, ctx) {
var html = record.get('text');
html += '
';
record.get('states').forEach(function(state) {
html += '
' +
state.state_name + ': ' + state.count.toString();
});
tooltip.setHtml(html);
}
},
subStyle: {
strokeStyle: false
}
}
]
},
{
flex: 1.6,
itemId: 'pgs',
padding: '0 10',
maxHeight: 250,
scrollable: true,
data: {
states: []
},
tpl: [
'' + 'PGs' + '
',
'',
' {state_name}:
',
'{count}
',
'',
''
]
}],
// similar to mgr dashboard
pgstates: {
// clean
clean: 1,
active: 1,
// working
activating: 2,
backfill_wait: 2,
backfilling: 2,
creating: 2,
deep: 2,
degraded: 2,
forced_backfill: 2,
forced_recovery: 2,
peered: 2,
peering: 2,
recovering: 2,
recovery_wait: 2,
remapped: 2,
repair: 2,
scrubbing: 2,
snaptrim: 2,
snaptrim_wait: 2,
// error
backfill_toofull: 3,
backfill_unfound: 3,
down: 3,
incomplete: 3,
inconsistent: 3,
recovery_toofull: 3,
recovery_unfound: 3,
snaptrim_error: 3,
stale: 3,
undersized: 3
},
statecategories: [
{
text: gettext('Unknown'),
count: 0,
states: [],
cls: 'faded'
},
{
text: gettext('Clean'),
cls: 'good'
},
{
text: gettext('Working'),
cls: 'warning'
},
{
text: gettext('Error'),
cls: 'critical'
}
],
updateAll: function(metadata, status) {
var me = this;
me.suspendLayout = true;
var maxversion = "0";
Object.values(metadata.version || {}).forEach(function(version) {
if (PVE.Utils.compare_ceph_versions(version, maxversion) > 0) {
maxversion = version;
}
});
var oldosds = [];
if (metadata.osd) {
metadata.osd.forEach(function(osd) {
var version = PVE.Utils.parse_ceph_version(osd);
if (version != maxversion) {
oldosds.push({
id: osd.id,
version: version
});
}
});
}
// update PGs sorted
var pgmap = status.pgmap || {};
var pgs_by_state = pgmap.pgs_by_state || [];
pgs_by_state.sort(function(a,b){
return (a.state_name < b.state_name)?-1:(a.state_name === b.state_name)?0:1;
});
me.statecategories.forEach(function(cat) {
cat.count = 0;
cat.states = [];
});
pgs_by_state.forEach(function(state) {
var i;
var states = state.state_name.split(/[^a-z]+/);
var result = 0;
for (i = 0; i < states.length; i++) {
if (me.pgstates[states[i]] > result) {
result = me.pgstates[states[i]];
}
}
// for the list
state.cls = me.statecategories[result].cls;
me.statecategories[result].count += state.count;
me.statecategories[result].states.push(state);
});
me.getComponent('pgchart').getStore().setData(me.statecategories);
me.getComponent('pgs').update({states: pgs_by_state});
var downinregex = /(\d+) osds down/;
var downin_osds = 0;
var health = status.health || {};
// we collect monitor/osd information from the checks
Ext.Object.each(health.checks, function(key, value, obj) {
var found = null;
if (key === 'OSD_DOWN') {
found = value.summary.message.match(downinregex);
if (found !== null) {
downin_osds = parseInt(found[1],10);
}
}
});
var osdmap = status.osdmap || {};
if (typeof osdmap.osdmap != "undefined") {
osdmap = osdmap.osdmap;
}
// update osds counts
var total_osds = osdmap.num_osds || 0;
var in_osds = osdmap.num_in_osds || 0;
var up_osds = osdmap.num_up_osds || 0;
var out_osds = total_osds - in_osds;
var down_osds = total_osds - up_osds;
var downout_osds = down_osds - downin_osds;
var upin_osds = in_osds - downin_osds;
var upout_osds = up_osds - upin_osds;
var osds = {
total: total_osds,
upin: upin_osds,
upout: upout_osds,
downin: downin_osds,
downout: downout_osds,
oldosds: oldosds
};
var osdcomponent = me.getComponent('osds');
osdcomponent.update(Ext.apply(osdcomponent.data, osds));
me.suspendLayout = false;
me.updateLayout();
}
});