mirror of
https://github.com/ceph/ceph
synced 2026-08-02 07:03:18 +00:00
mgr/dashboard: add button toggle to switch between new and old landing page
Signed-off-by: Pedro Gonzalez Gomez <pegonzal@redhat.com>
This commit is contained in:
parent
313921afcf
commit
21dc93ae11
BIN
doc/mgr/capacity-card.png
Normal file
BIN
doc/mgr/capacity-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
doc/mgr/cluster-utilization-card.png
Normal file
BIN
doc/mgr/cluster-utilization-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 67 KiB |
BIN
doc/mgr/dashboard-landing-page.png
Normal file
BIN
doc/mgr/dashboard-landing-page.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
@ -127,62 +127,67 @@ The Ceph Dashboard offers the following monitoring and management capabilities:
|
||||
Overview of the Dashboard Landing Page
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Displays overall cluster status, performance, and capacity metrics. Shows instant
|
||||
feedback for changes in the cluster and provides easy access to subpages of the
|
||||
dashboard.
|
||||
The landing page of Ceph Dashboard serves as the home page and features metrics
|
||||
such as the overall cluster status, performance, and capacity. It provides real-time
|
||||
updates on any changes in the cluster and allows quick access to other sections of the dashboard.
|
||||
|
||||
.. image:: dashboard-landing-page.png
|
||||
|
||||
|
||||
.. note::
|
||||
You can change the landing page to the previous version from:
|
||||
``Cluster >> Manager Modules >> Dashboard >> Edit``.
|
||||
Editing the ``FEATURE_TOGGLE_DASHBOARD`` option will change the landing page, from one view to another.
|
||||
|
||||
Note that the previous version of the landing page will be disabled in future releases.
|
||||
|
||||
.. _dashboard-landing-page-details:
|
||||
|
||||
Details
|
||||
"""""""
|
||||
Provides an overview of the cluster configuration, displaying various critical aspects of the cluster.
|
||||
|
||||
.. image:: details-card.png
|
||||
|
||||
.. _dashboard-landing-page-status:
|
||||
|
||||
Status
|
||||
""""""
|
||||
Provides a visual indication of cluster health, and displays cluster alerts grouped by severity.
|
||||
|
||||
* **Cluster Status**: Displays overall cluster health. In case of any error it
|
||||
displays a short description of the error and provides a link to the logs.
|
||||
* **Hosts**: Displays the total number of hosts associated to the cluster and
|
||||
links to a subpage that lists and describes each.
|
||||
* **Monitors**: Displays mons and their quorum status and
|
||||
open sessions. Links to a subpage that lists and describes each.
|
||||
* **OSDs**: Displays object storage daemons (ceph-osds) and
|
||||
the numbers of OSDs running (up), in service
|
||||
(in), and out of the cluster (out). Provides links to
|
||||
subpages providing a list of all OSDs and related management actions.
|
||||
* **Managers**: Displays active and standby Ceph Manager
|
||||
daemons (ceph-mgr).
|
||||
* **Object Gateway**: Displays active object gateways (RGWs) and
|
||||
provides links to subpages that list all object gateway daemons.
|
||||
* **Metadata Servers**: Displays active and standby CephFS metadata
|
||||
service daemons (ceph-mds).
|
||||
* **iSCSI Gateways**: Display iSCSI gateways available,
|
||||
active (up), and inactive (down). Provides a link to a subpage
|
||||
showing a list of all iSCSI Gateways.
|
||||
.. image:: status-card-open.png
|
||||
|
||||
.. _dashboard-landing-page-capacity:
|
||||
|
||||
Capacity
|
||||
""""""""
|
||||
* **Used**: Displays the used capacity out of the total physical capacity providedd by storage nodes (OSDs)
|
||||
* **Warning**: Displays the `nearfull` threshold of the OSDs
|
||||
* **Danger**: Displays the `full` threshold of the OSDs
|
||||
|
||||
* **Raw Capacity**: Displays the capacity used out of the total
|
||||
physical capacity provided by storage nodes (OSDs).
|
||||
* **Objects**: Displays the number and status of RADOS objects
|
||||
including the percentages of healthy, misplaced, degraded, and unfound
|
||||
objects.
|
||||
* **PG Status**: Displays the total number of placement groups and
|
||||
their status, including the percentage clean, working,
|
||||
warning, and unknown.
|
||||
* **Pools**: Displays pools and links to a subpage listing details.
|
||||
* **PGs per OSD**: Displays the number of placement groups assigned to
|
||||
object storage daemons.
|
||||
.. image:: capacity-card.png
|
||||
|
||||
.. _dashboard-landing-page-inventory:
|
||||
|
||||
Inventory
|
||||
"""""""""
|
||||
An inventory for all assets within the cluster.
|
||||
Provides direct access to subpages of the dashboard from each item of this card.
|
||||
|
||||
.. image:: inventory-card.png
|
||||
|
||||
.. _dashboard-landing-page-performance:
|
||||
|
||||
Performance
|
||||
"""""""""""
|
||||
Cluster Utilization
|
||||
"""""""""""""""""""
|
||||
* **Used Capacity**: Total capacity used of the cluster. The maximum value of the chart is the maximum capacity of the cluster.
|
||||
* **IOPS (Input/Output Operations Per Second)**: Number of read and write operations.
|
||||
* **Latency**: Amount of time that it takes to process a read or a write request.
|
||||
* **Client Throughput**: Amount of data that clients read or write to the cluster.
|
||||
* **Recovery Throughput**: Amount of recovery data that clients read or write to the cluster.
|
||||
|
||||
* **Client READ/Write**: Displays an overview of
|
||||
client input and output operations.
|
||||
* **Client Throughput**: Displays the data transfer rates to and from Ceph clients.
|
||||
* **Recovery throughput**: Displays rate of cluster healing and balancing operations.
|
||||
* **Scrubbing**: Displays light and deep scrub status.
|
||||
|
||||
.. image:: cluster-utilization-card.png
|
||||
|
||||
Supported Browsers
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
BIN
doc/mgr/details-card.png
Normal file
BIN
doc/mgr/details-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
doc/mgr/inventory-card.png
Normal file
BIN
doc/mgr/inventory-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
doc/mgr/status-card-open.png
Normal file
BIN
doc/mgr/status-card-open.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@ -24,8 +24,7 @@ import { SilenceListComponent } from './ceph/cluster/prometheus/silence-list/sil
|
||||
import { ServiceFormComponent } from './ceph/cluster/services/service-form/service-form.component';
|
||||
import { ServicesComponent } from './ceph/cluster/services/services.component';
|
||||
import { TelemetryComponent } from './ceph/cluster/telemetry/telemetry.component';
|
||||
import { DeprecatedDashboardComponent } from './ceph/dashboard/dashboard/dashboard.component';
|
||||
import { DashboardComponent } from './ceph/new-dashboard/dashboard/dashboard.component';
|
||||
import { DashboardComponent } from './ceph/dashboard/dashboard/dashboard.component';
|
||||
import { NfsFormComponent } from './ceph/nfs/nfs-form/nfs-form.component';
|
||||
import { NfsListComponent } from './ceph/nfs/nfs-list/nfs-list.component';
|
||||
import { PerformanceCounterComponent } from './ceph/performance-counter/performance-counter/performance-counter.component';
|
||||
@ -89,8 +88,7 @@ const routes: Routes = [
|
||||
canActivate: [AuthGuardService, ChangePasswordGuardService],
|
||||
canActivateChild: [AuthGuardService, ChangePasswordGuardService],
|
||||
children: [
|
||||
{ path: 'dashboard', component: DeprecatedDashboardComponent },
|
||||
{ path: 'dashboard_3', component: DashboardComponent },
|
||||
{ path: 'dashboard', component: DashboardComponent },
|
||||
{ path: 'error', component: ErrorComponent },
|
||||
|
||||
// Cluster
|
||||
|
||||
@ -5,7 +5,6 @@ import { SharedModule } from '../shared/shared.module';
|
||||
import { CephfsModule } from './cephfs/cephfs.module';
|
||||
import { ClusterModule } from './cluster/cluster.module';
|
||||
import { DashboardModule } from './dashboard/dashboard.module';
|
||||
import { NewDashboardModule } from './new-dashboard/dashboard.module';
|
||||
import { NfsModule } from './nfs/nfs.module';
|
||||
import { PerformanceCounterModule } from './performance-counter/performance-counter.module';
|
||||
|
||||
@ -14,7 +13,6 @@ import { PerformanceCounterModule } from './performance-counter/performance-coun
|
||||
CommonModule,
|
||||
ClusterModule,
|
||||
DashboardModule,
|
||||
NewDashboardModule,
|
||||
PerformanceCounterModule,
|
||||
CephfsModule,
|
||||
NfsModule,
|
||||
|
||||
@ -13,7 +13,7 @@ import { CardComponent } from './card/card.component';
|
||||
import { DashboardAreaChartComponent } from './dashboard-area-chart/dashboard-area-chart.component';
|
||||
import { DashboardPieComponent } from './dashboard-pie/dashboard-pie.component';
|
||||
import { DashboardTimeSelectorComponent } from './dashboard-time-selector/dashboard-time-selector.component';
|
||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||
import { DashboardV3Component } from './dashboard/dashboard-v3.component';
|
||||
import { CardRowComponent } from './card-row/card-row.component';
|
||||
import { PgSummaryPipe } from './pg-summary.pipe';
|
||||
|
||||
@ -33,13 +33,15 @@ import { PgSummaryPipe } from './pg-summary.pipe';
|
||||
],
|
||||
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
DashboardV3Component,
|
||||
CardComponent,
|
||||
DashboardPieComponent,
|
||||
CardRowComponent,
|
||||
PgSummaryPipe,
|
||||
DashboardAreaChartComponent,
|
||||
DashboardTimeSelectorComponent
|
||||
]
|
||||
],
|
||||
|
||||
exports: [DashboardV3Component]
|
||||
})
|
||||
export class NewDashboardModule {}
|
||||
export class DashboardV3Module {}
|
||||
@ -24,7 +24,7 @@ import { CardRowComponent } from '../card-row/card-row.component';
|
||||
import { CardComponent } from '../card/card.component';
|
||||
import { DashboardPieComponent } from '../dashboard-pie/dashboard-pie.component';
|
||||
import { PgSummaryPipe } from '../pg-summary.pipe';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { DashboardV3Component } from './dashboard-v3.component';
|
||||
|
||||
export class SummaryServiceMock {
|
||||
summaryDataSource = new BehaviorSubject({
|
||||
@ -40,8 +40,8 @@ export class SummaryServiceMock {
|
||||
}
|
||||
|
||||
describe('Dashbord Component', () => {
|
||||
let component: DashboardComponent;
|
||||
let fixture: ComponentFixture<DashboardComponent>;
|
||||
let component: DashboardV3Component;
|
||||
let fixture: ComponentFixture<DashboardV3Component>;
|
||||
let configurationService: ConfigurationService;
|
||||
let orchestratorService: MgrModuleService;
|
||||
let getHealthSpy: jasmine.Spy;
|
||||
@ -153,7 +153,7 @@ describe('Dashbord Component', () => {
|
||||
configureTestBed({
|
||||
imports: [RouterTestingModule, HttpClientTestingModule, ToastrModule.forRoot(), SharedModule],
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
DashboardV3Component,
|
||||
CardComponent,
|
||||
DashboardPieComponent,
|
||||
CardRowComponent,
|
||||
@ -184,7 +184,7 @@ describe('Dashbord Component', () => {
|
||||
rgw: true
|
||||
})
|
||||
);
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
fixture = TestBed.createComponent(DashboardV3Component);
|
||||
component = fixture.componentInstance;
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
orchestratorService = TestBed.inject(MgrModuleService);
|
||||
@ -306,7 +306,7 @@ describe('Dashbord Component', () => {
|
||||
rgw: false
|
||||
})
|
||||
);
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
fixture = TestBed.createComponent(DashboardV3Component);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
@ -27,11 +27,11 @@ import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helpe
|
||||
import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.scss']
|
||||
selector: 'cd-dashboard-v3',
|
||||
templateUrl: './dashboard-v3.component.html',
|
||||
styleUrls: ['./dashboard-v3.component.scss']
|
||||
})
|
||||
export class DashboardComponent extends PrometheusListHelper implements OnInit, OnDestroy {
|
||||
export class DashboardV3Component extends PrometheusListHelper implements OnInit, OnDestroy {
|
||||
detailsCardData: DashboardDetails = {};
|
||||
osdSettingsService: any;
|
||||
osdSettings: any;
|
||||
@ -105,6 +105,9 @@ export class DashboardComponent extends PrometheusListHelper implements OnInit,
|
||||
|
||||
ngOnDestroy() {
|
||||
this.interval.unsubscribe();
|
||||
if (this.timerGetPrometheusDataSub) {
|
||||
this.timerGetPrometheusDataSub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
getHealth() {
|
||||
@ -7,9 +7,10 @@ import { NgbNavModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ChartsModule } from 'ng2-charts';
|
||||
|
||||
import { SharedModule } from '~/app/shared/shared.module';
|
||||
import { DashboardV3Module } from '../dashboard-v3/dashboard-v3.module';
|
||||
import { CephSharedModule } from '../shared/ceph-shared.module';
|
||||
import { FeedbackComponent } from '../shared/feedback/feedback.component';
|
||||
import { DeprecatedDashboardComponent } from './dashboard/dashboard.component';
|
||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||
import { HealthPieComponent } from './health-pie/health-pie.component';
|
||||
import { HealthComponent } from './health/health.component';
|
||||
import { InfoCardComponent } from './info-card/info-card.component';
|
||||
@ -29,12 +30,13 @@ import { OsdSummaryPipe } from './osd-summary.pipe';
|
||||
RouterModule,
|
||||
NgbPopoverModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule
|
||||
ReactiveFormsModule,
|
||||
DashboardV3Module
|
||||
],
|
||||
|
||||
declarations: [
|
||||
HealthComponent,
|
||||
DeprecatedDashboardComponent,
|
||||
DashboardComponent,
|
||||
MonSummaryPipe,
|
||||
OsdSummaryPipe,
|
||||
MgrSummaryPipe,
|
||||
|
||||
@ -1,32 +1,15 @@
|
||||
<main aria-label="Dashboard" >
|
||||
<main aria-label="Dashboard">
|
||||
<a href="#main"
|
||||
class="sr-only">skip to content</a>
|
||||
|
||||
<cd-refresh-selector></cd-refresh-selector>
|
||||
<ng-container *ngIf="(enabledFeature$ | async)?.dashboard === false; else dashboardV3"
|
||||
class="main-padding">
|
||||
<cd-refresh-selector></cd-refresh-selector>
|
||||
|
||||
<ng-container *ngIf="hasGrafana">
|
||||
<nav ngbNav
|
||||
#nav="ngbNav"
|
||||
class="nav-tabs">
|
||||
<ng-container ngbNavItem>
|
||||
<a ngbNavLink
|
||||
i18n>Health</a>
|
||||
<ng-template ngbNavContent>
|
||||
<cd-health></cd-health>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<ng-container ngbNavItem>
|
||||
<a ngbNavLink
|
||||
i18n>Statistics</a>
|
||||
<ng-template ngbNavContent>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
</nav>
|
||||
|
||||
<div [ngbNavOutlet]="nav"></div>
|
||||
<cd-health id="main"></cd-health>
|
||||
</ng-container>
|
||||
|
||||
<cd-health id="main"
|
||||
*ngIf="!hasGrafana"></cd-health>
|
||||
<ng-template #dashboardV3>
|
||||
<cd-dashboard-v3></cd-dashboard-v3>
|
||||
</ng-template>
|
||||
</main>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
main {
|
||||
main:has(cd-health) {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
@ -1,23 +1,26 @@
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { FeatureTogglesService } from '~/app/shared/services/feature-toggles.service';
|
||||
|
||||
import { configureTestBed } from '~/testing/unit-test-helper';
|
||||
import { DeprecatedDashboardComponent } from './dashboard.component';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
|
||||
describe('DashboardComponent', () => {
|
||||
let component: DeprecatedDashboardComponent;
|
||||
let fixture: ComponentFixture<DeprecatedDashboardComponent>;
|
||||
let component: DashboardComponent;
|
||||
let fixture: ComponentFixture<DashboardComponent>;
|
||||
|
||||
configureTestBed({
|
||||
imports: [NgbNavModule],
|
||||
declarations: [DeprecatedDashboardComponent],
|
||||
imports: [NgbNavModule, HttpClientTestingModule],
|
||||
declarations: [DashboardComponent],
|
||||
providers: [FeatureTogglesService],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DeprecatedDashboardComponent);
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { FeatureTogglesService } from '~/app/shared/services/feature-toggles.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.scss']
|
||||
})
|
||||
export class DeprecatedDashboardComponent {
|
||||
hasGrafana = false; // TODO: Temporary var, remove when grafana is implemented
|
||||
export class DashboardComponent {
|
||||
enabledFeature$: Observable<Object>;
|
||||
|
||||
constructor(private featureToggles: FeatureTogglesService) {
|
||||
this.enabledFeature$ = this.featureToggles.get();
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,6 +100,10 @@
|
||||
color: vv.$gray-200;
|
||||
}
|
||||
|
||||
.no-hover:hover {
|
||||
background-color: vv.$secondary !important;
|
||||
}
|
||||
|
||||
@media (min-width: vv.$screen-md-min) {
|
||||
.cd-navbar-utility {
|
||||
border-bottom: 0;
|
||||
|
||||
@ -12,6 +12,7 @@ export class FeatureTogglesMap {
|
||||
cephfs = true;
|
||||
rgw = true;
|
||||
nfs = true;
|
||||
dashboardV3 = true;
|
||||
}
|
||||
export type Features = keyof FeatureTogglesMap;
|
||||
export type FeatureTogglesMap$ = Observable<FeatureTogglesMap>;
|
||||
|
||||
@ -2858,6 +2858,9 @@ paths:
|
||||
cephfs:
|
||||
description: ''
|
||||
type: boolean
|
||||
dashboard:
|
||||
description: ''
|
||||
type: boolean
|
||||
iscsi:
|
||||
description: ''
|
||||
type: boolean
|
||||
@ -2880,6 +2883,7 @@ paths:
|
||||
- cephfs
|
||||
- rgw
|
||||
- nfs
|
||||
- dashboard
|
||||
type: object
|
||||
description: OK
|
||||
'400':
|
||||
|
||||
@ -25,6 +25,7 @@ class Features(Enum):
|
||||
CEPHFS = 'cephfs'
|
||||
RGW = 'rgw'
|
||||
NFS = 'nfs'
|
||||
DASHBOARD = 'dashboard'
|
||||
|
||||
|
||||
PREDISABLED_FEATURES = set() # type: Set[str]
|
||||
@ -140,7 +141,8 @@ class FeatureToggles(I.CanMgr, I.Setupable, I.HasOptions,
|
||||
"iscsi": (bool, ''),
|
||||
"cephfs": (bool, ''),
|
||||
"rgw": (bool, ''),
|
||||
"nfs": (bool, '')
|
||||
"nfs": (bool, ''),
|
||||
"dashboard": (bool, '')
|
||||
}
|
||||
|
||||
@APIRouter('/feature_toggles')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user