]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/ceph/StatusDetail.js
update shipped appliance info index
[pve-manager.git] / www / manager6 / ceph / StatusDetail.js
index dfd6d103f360f64b7a19fd9e81ad220310ad597e..2196f1db51d9d4134ea6b2a7a4c3467126ce202b 100644 (file)
@@ -27,10 +27,11 @@ Ext.define('PVE.ceph.StatusDetail', {
            upout: 0,
            downin: 0,
            downout: 0,
-           oldosds: [],
+           oldOSD: [],
+           ghostOSD: [],
        },
        tpl: [
-           '<h3>' + 'OSDs' + '</h3>',
+           '<h3>OSDs</h3>',
            '<table class="osds">',
            '<tr><td></td>',
            '<td><i class="fa fa-fw good fa-circle"></i>',
@@ -59,16 +60,27 @@ Ext.define('PVE.ceph.StatusDetail', {
            gettext('Total'),
            ': {total}',
            '</div><br />',
-           '<tpl if="oldosds.length &gt; 0">',
+           '<tpl if="oldOSD.length &gt; 0">',
            '<i class="fa fa-refresh warning"></i> ' + gettext('Outdated OSDs') + "<br>",
            '<div class="osds">',
-           '<tpl for="oldosds">',
+           '<tpl for="oldOSD">',
            '<div class="left-aligned">osd.{id}:</div>',
            '<div class="right-aligned">{version}</div><br />',
            '<div style="clear:both"></div>',
            '</tpl>',
            '</div>',
            '</tpl>',
+           '</div>',
+           '<tpl if="ghostOSD.length &gt; 0">',
+           '<br />',
+           `<i class="fa fa-question-circle warning"></i> ${gettext('Ghost OSDs')}<br>`,
+           `<div data-qtip="${gettext('OSDs with no metadata, possibly left over from removal')}" class="osds">`,
+           '<tpl for="ghostOSD">',
+           '<div class="left-aligned">osd.{id}</div>',
+           '<div style="clear:both"></div>',
+           '</tpl>',
+           '</div>',
+           '</tpl>',
        ],
     },
     {
@@ -82,6 +94,7 @@ Ext.define('PVE.ceph.StatusDetail', {
        colors: [
            '#CFCFCF',
            '#21BF4B',
+           '#3892d4',
            '#FFCC00',
            '#FF6C59',
        ],
@@ -119,7 +132,7 @@ Ext.define('PVE.ceph.StatusDetail', {
            states: [],
        },
        tpl: [
-           '<h3>' + 'PGs' + '</h3>',
+           '<h3>PGs</h3>',
            '<tpl for="states">',
            '<div class="left-aligned"><i class ="fa fa-circle {cls}"></i> {state_name}:</div>',
            '<div class="right-aligned">{count}</div><br />',
@@ -134,13 +147,12 @@ Ext.define('PVE.ceph.StatusDetail', {
        clean: 1,
        active: 1,
 
-       // working
+       // busy
        activating: 2,
        backfill_wait: 2,
        backfilling: 2,
        creating: 2,
        deep: 2,
-       degraded: 2,
        forced_backfill: 2,
        forced_recovery: 2,
        peered: 2,
@@ -153,17 +165,20 @@ Ext.define('PVE.ceph.StatusDetail', {
        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,
+       // warning
+       degraded: 3,
        undersized: 3,
+
+       // critical
+       backfill_toofull: 4,
+       backfill_unfound: 4,
+       down: 4,
+       incomplete: 4,
+       inconsistent: 4,
+       recovery_toofull: 4,
+       recovery_unfound: 4,
+       snaptrim_error: 4,
+       stale: 4,
     },
 
     statecategories: [
@@ -178,43 +193,65 @@ Ext.define('PVE.ceph.StatusDetail', {
            cls: 'good',
        },
        {
-           text: gettext('Working'),
+           text: gettext('Busy'),
+           cls: 'pve-ceph-status-busy',
+       },
+       {
+           text: gettext('Warning'),
            cls: 'warning',
        },
        {
-           text: gettext('Error'),
+           text: gettext('Critical'),
            cls: 'critical',
        },
     ],
 
+    checkThemeColors: function() {
+       let me = this;
+       let rootStyle = getComputedStyle(document.documentElement);
+
+       // get color
+       let background = rootStyle.getPropertyValue("--pwt-panel-background").trim() || "#ffffff";
+
+       // set the colors
+       me.chart.setBackground(background);
+       me.chart.redraw();
+    },
+
     updateAll: function(metadata, status) {
-       var me = this;
+       let 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;
+       let maxversion = "0";
+       Object.values(metadata.node || {}).forEach(function(node) {
+           if (PVE.Utils.compare_ceph_versions(node?.version?.parts, maxversion) > 0) {
+               maxversion = node.version.parts;
            }
        });
 
-       var oldosds = [];
-
-       if (metadata.osd) {
-           metadata.osd.forEach(function(osd) {
-               var version = PVE.Utils.parse_ceph_version(osd);
-               if (version != maxversion) {
-                   oldosds.push({
+       let oldOSD = [], ghostOSD = [];
+       metadata.osd?.forEach(osd => {
+           let version = PVE.Utils.parse_ceph_version(osd);
+           if (version !== undefined) {
+               if (PVE.Utils.compare_ceph_versions(version, maxversion) !== 0) {
+                   oldOSD.push({
                        id: osd.id,
                        version: version,
                    });
                }
-           });
-       }
+           } else {
+               if (Object.keys(osd).length > 1) {
+                   console.warn('got OSD entry with no valid version but other keys', osd);
+               }
+               ghostOSD.push({
+                   id: osd.id,
+               });
+           }
+       });
 
        // update PGs sorted
-       var pgmap = status.pgmap || {};
-       var pgs_by_state = pgmap.pgs_by_state || [];
+       let pgmap = status.pgmap || {};
+       let 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;
        });
@@ -225,10 +262,9 @@ Ext.define('PVE.ceph.StatusDetail', {
        });
 
        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++) {
+           let states = state.state_name.split(/[^a-z]+/);
+           let result = 0;
+           for (let i = 0; i < states.length; i++) {
                if (me.pgstates[states[i]] > result) {
                    result = me.pgstates[states[i]];
                }
@@ -240,14 +276,13 @@ Ext.define('PVE.ceph.StatusDetail', {
            me.statecategories[result].states.push(state);
        });
 
-       me.getComponent('pgchart').getStore().setData(me.statecategories);
+       me.chart.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 || {};
+       let health = status.health || {};
        // we collect monitor/osd information from the checks
+       const downinregex = /(\d+) osds down/;
+       let downin_osds = 0;
        Ext.Object.each(health.checks, function(key, value, obj) {
            var found = null;
            if (key === 'OSD_DOWN') {
@@ -258,33 +293,55 @@ Ext.define('PVE.ceph.StatusDetail', {
            }
        });
 
-       var osdmap = status.osdmap || {};
-       if (typeof osdmap.osdmap != "undefined") {
+       let 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;
+       // update OSDs counts
+       let total_osds = osdmap.num_osds || 0;
+       let in_osds = osdmap.num_in_osds || 0;
+       let up_osds = osdmap.num_up_osds || 0;
+       let 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 = {
+       let downout_osds = down_osds - downin_osds;
+       let upin_osds = in_osds - downin_osds;
+       let upout_osds = up_osds - upin_osds;
+
+       let osds = {
            total: total_osds,
            upin: upin_osds,
            upout: upout_osds,
            downin: downin_osds,
            downout: downout_osds,
-           oldosds: oldosds,
+           oldOSD: oldOSD,
+           ghostOSD,
        };
-       var osdcomponent = me.getComponent('osds');
+       let osdcomponent = me.getComponent('osds');
        osdcomponent.update(Ext.apply(osdcomponent.data, osds));
 
        me.suspendLayout = false;
        me.updateLayout();
     },
+
+     initComponent: function() {
+       var me = this;
+       me.callParent();
+
+       me.chart = me.getComponent('pgchart');
+       me.checkThemeColors();
+
+       // switch colors on media query changes
+       me.mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
+       me.themeListener = (e) => { me.checkThemeColors(); };
+       me.mediaQueryList.addEventListener("change", me.themeListener);
+    },
+
+    doDestroy: function() {
+       let me = this;
+
+       me.mediaQueryList.removeEventListener("change", me.themeListener);
+
+       me.callParent();
+    },
 });