From: Aashish Sharma Date: Thu, 5 Oct 2023 05:38:30 +0000 (+0530) Subject: mgr/dashboard: Show which daemons failed in CEPHADM_FAILED_DAEMON X-Git-Tag: v20.0.0~1712^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=5a44b395d4fd86f51fe7431a8f8f539ee57eeee7;p=ceph.git mgr/dashboard: Show which daemons failed in CEPHADM_FAILED_DAEMON healthcheck Fixes: https://tracker.ceph.com/issues/63792 Signed-off-by: Aashish Sharma --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/upgrade/upgrade.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/upgrade/upgrade.component.html index 5db15a42b51a3..3e7f7a2c09034 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/upgrade/upgrade.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/upgrade/upgrade.component.html @@ -47,13 +47,7 @@ id="clusterStatus">
-
    -
  • - - {{ check.type }}: {{ check.summary.message }} -
  • -
+
- -
    -
  • - - {{ check.type }}: {{ check.summary.message }} -
  • -
+
@@ -168,7 +162,7 @@ popoverClass="info-card-popover-cluster-status" [openDelay]="300" [closeDelay]="500" - triggers="mouseenter:mouseleave" + triggers="mouseenter" *ngIf="healthData.health?.checks?.length" i18n>Cluster - -
    -
  • - - {{ check.type }}: {{ check.summary.message }} -
  • -
+
+
    +
  • + + {{ check.type }}: {{ check.summary.message }}
    +
    + + Failed Daemons: +
    + {{ failedDaemons }} + {{ !last ? ', ' : '' }} +
    +
    +
    +
    + {{ details?.message }} +
    +
  • +
+ + + + + + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts new file mode 100644 index 0000000000000..e9a4da80fd6c8 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts @@ -0,0 +1,50 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HealthChecksComponent } from './health-checks.component'; +import { HealthColorPipe } from '~/app/shared/pipes/health-color.pipe'; +import { By } from '@angular/platform-browser'; +import { CssHelper } from '~/app/shared/classes/css-helper'; + +describe('HealthChecksComponent', () => { + let component: HealthChecksComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HealthChecksComponent, HealthColorPipe], + providers: [CssHelper] + }).compileComponents(); + + fixture = TestBed.createComponent(HealthChecksComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should show the correct health warning for failed daemons', () => { + component.healthData = [ + { + severity: 'HEALTH_WARN', + summary: { + message: '1 failed cephadm daemon(s)', + count: 1 + }, + detail: [ + { + message: 'daemon ceph-exporter.ceph-node-00 on ceph-node-00 is in error state' + } + ], + muted: false, + type: 'CEPHADM_FAILED_DAEMON' + } + ]; + fixture.detectChanges(); + const failedDaemons = fixture.debugElement.query(By.css('.failed-daemons')); + expect(failedDaemons.nativeElement.textContent).toContain( + 'Failed Daemons: ceph-exporter.ceph-node-00 ' + ); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.ts new file mode 100644 index 0000000000000..6c047bc4b781d --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.ts @@ -0,0 +1,28 @@ +import { Component, Input } from '@angular/core'; +import { Icons } from '~/app/shared/enum/icons.enum'; +import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; +import { Permissions } from '~/app/shared/models/permissions'; + +@Component({ + selector: 'cd-health-checks', + templateUrl: './health-checks.component.html', + styleUrls: ['./health-checks.component.scss'] +}) +export class HealthChecksComponent { + @Input() + healthData: any; + + icons = Icons; + + permissions: Permissions; + + constructor(private authStorageService: AuthStorageService) { + this.permissions = this.authStorageService.getPermissions(); + } + + getFailedDaemons(detail: any[]): string[] { + return detail.map( + (failedDaemons) => failedDaemons.message.split('daemon ')?.[1].split(' on ')[0] + ); + } +}