]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Show which daemons failed in CEPHADM_FAILED_DAEMON 59597/head
authorAashish Sharma <aasharma@li-e74156cc-2f67-11b2-a85c-e98659a63c5c.ibm.com>
Thu, 5 Oct 2023 05:38:30 +0000 (11:08 +0530)
committerAashish Sharma <aasharma@li-e74156cc-2f67-11b2-a85c-e98659a63c5c.ibm.com>
Wed, 4 Sep 2024 11:21:15 +0000 (16:51 +0530)
healthcheck

Fixes: https://tracker.ceph.com/issues/63792
Signed-off-by: Aashish Sharma <aasharma@redhat.com>
(cherry picked from commit 5a44b395d4fd86f51fe7431a8f8f539ee57eeee7)

src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/upgrade/upgrade.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard/dashboard-v3.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/ceph-shared.module.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.html [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.scss [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.ts [new file with mode: 0644]

index 5db15a42b51a348d82d1bd7c6d19e97be8460d5f..3e7f7a2c0903459852fb1fcbbe343389a17dec23 100644 (file)
              id="clusterStatus">
       <div class="d-flex flex-column justify-content-center align-items-center">
         <ng-template #healthChecks>
-          <ul>
-            <li *ngFor="let check of healthData.health.checks">
-              <span [ngStyle]="check.severity | healthColor"
-                    [class.health-warn-description]="check.severity === 'HEALTH_WARN'">
-              {{ check.type }}</span>: {{ check.summary.message }}
-            </li>
-          </ul>
+          <cd-health-checks [healthData]="healthData.health.checks"></cd-health-checks>
         </ng-template>
         <ng-template #healthWarningAndError>
         <div class="info-card-content-clickable mt-1"
index ee01993703a0d6a835a8262647b643143d390fdf..ac0110728e38f1ad1b572350637d191ab4af142f 100644 (file)
             </div>
             <div class="d-flex flex-column ms-4 me-4 mt-4 mb-4">
               <ng-template #healthChecks>
-                <ng-container *ngTemplateOutlet="logsLink"></ng-container>
-                <ul>
-                  <li *ngFor="let check of healthData.health.checks">
-                    <span [ngStyle]="check.severity | healthColor"
-                          [class.health-warn-description]="check.severity === 'HEALTH_WARN'">
-                    {{ check.type }}</span>: {{ check.summary.message }}
-                  </li>
-                </ul>
+                <cd-health-checks *ngIf="healthData?.health?.checks"
+                                  [healthData]="healthData.health.checks"></cd-health-checks>
               </ng-template>
 
               <div class="d-flex flex-row">
                    popoverClass="info-card-popover-cluster-status"
                    [openDelay]="300"
                    [closeDelay]="500"
-                   triggers="mouseenter:mouseleave"
+                   triggers="mouseenter"
                    *ngIf="healthData.health?.checks?.length"
                    i18n>Cluster</a>
                 <span class="ms-2 mt-n1 lead"
index c440a5f2df0de416a834d0471e78e9f733f84361..9e68fc22ca0ada5751e97ab2aeccc62301af63e2 100644 (file)
                   *ngIf="healthData.health?.status">
       <ng-container *ngIf="healthData.health?.checks?.length > 0">
         <ng-template #healthChecks>
-          <ng-container *ngTemplateOutlet="logsLink"></ng-container>
-          <ul>
-            <li *ngFor="let check of healthData.health.checks">
-              <span [ngStyle]="check.severity | healthColor"
-                    [class.health-warn-description]="check.severity === 'HEALTH_WARN'">
-              {{ check.type }}</span>: {{ check.summary.message }}
-            </li>
-          </ul>
+          <cd-health-checks [healthData]="healthData"></cd-health-checks>
         </ng-template>
         <div class="info-card-content-clickable"
              [ngStyle]="healthData.health.status | healthColor"
index 9e9f2917a47499b21c39ac453f2c470c4f5aa960..9e276d5903b9b55ed76b89f8dc0c73afa15816b2 100644 (file)
@@ -8,10 +8,11 @@ import { DataTableModule } from '~/app/shared/datatable/datatable.module';
 import { SharedModule } from '~/app/shared/shared.module';
 import { DeviceListComponent } from './device-list/device-list.component';
 import { SmartListComponent } from './smart-list/smart-list.component';
+import { HealthChecksComponent } from './health-checks/health-checks.component';
 
 @NgModule({
   imports: [CommonModule, DataTableModule, SharedModule, NgbNavModule, NgxPipeFunctionModule],
-  exports: [DeviceListComponent, SmartListComponent],
-  declarations: [DeviceListComponent, SmartListComponent]
+  exports: [DeviceListComponent, SmartListComponent, HealthChecksComponent],
+  declarations: [DeviceListComponent, SmartListComponent, HealthChecksComponent]
 })
 export class CephSharedModule {}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.html
new file mode 100644 (file)
index 0000000..9e9ff96
--- /dev/null
@@ -0,0 +1,28 @@
+<ng-container *ngTemplateOutlet="logsLink"></ng-container>
+<ul>
+  <li *ngFor="let check of healthData">
+    <span [ngStyle]="check.severity | healthColor"
+          [class.health-warn-description]="check.severity === 'HEALTH_WARN'">
+    {{ check.type }}</span>: {{ check.summary.message }} <br>
+    <div *ngIf="check.type === 'CEPHADM_FAILED_DAEMON'"
+         class="failed-daemons">
+      <cd-help-text>
+        <b>Failed Daemons:</b>
+        <div *ngFor="let failedDaemons of getFailedDaemons(check.detail); let last = last">
+          {{ failedDaemons }}
+          {{ !last ? ', ' : '' }}
+        </div>
+      </cd-help-text>
+    </div>
+    <div *ngFor="let details of check?.detail">
+      <cd-help-text>{{ details?.message }}</cd-help-text>
+    </div>
+  </li>
+</ul>
+
+<ng-template #logsLink>
+  <ng-container *ngIf="permissions.log.read">
+    <p class="logs-link"
+        i18n><i [ngClass]="[icons.infoCircle]"></i> See <a routerLink="/logs">Logs</a> for more details.</p>
+  </ng-container>
+</ng-template>
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 (file)
index 0000000..e69de29
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 (file)
index 0000000..e9a4da8
--- /dev/null
@@ -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<HealthChecksComponent>;
+
+  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 (file)
index 0000000..6c047bc
--- /dev/null
@@ -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]
+    );
+  }
+}