parameters={'status': (str, 'Cluster Status')})
def singleton_set(self, status: str):
ClusterModel(status).to_db()
+
+ @RESTController.Collection('GET', 'capacity')
+ def get_capacity(self):
+ return ClusterModel.get_capacity()
--- /dev/null
+<div class="chart-container">
+ <canvas baseChart
+ #chartCanvas
+ [datasets]="chartConfig.dataset"
+ [chartType]="chartConfig.chartType"
+ [options]="chartConfig.options"
+ [labels]="chartConfig.labels"
+ [colors]="chartConfig.colors"
+ [plugins]="doughnutChartPlugins"
+ class="chart-canvas">
+ </canvas>
+ <div class="chartjs-tooltip"
+ #chartTooltip>
+ <table></table>
+ </div>
+</div>
--- /dev/null
+@use './src/styles/chart-tooltip';
+
+$canvas-width: 100%;
+$canvas-height: 100%;
+
+.chart-container {
+ height: $canvas-height;
+ margin-left: auto;
+ margin-right: auto;
+ position: unset;
+ width: $canvas-width;
+}
+
+.chart-canvas {
+ height: $canvas-height;
+ margin-left: auto;
+ margin-right: auto;
+ max-height: $canvas-height;
+ max-width: $canvas-width;
+ position: unset;
+ width: $canvas-width;
+}
--- /dev/null
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CssHelper } from '~/app/shared/classes/css-helper';
+import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
+import { configureTestBed } from '~/testing/unit-test-helper';
+import { DashboardPieComponent } from './dashboard-pie.component';
+
+describe('DashboardPieComponent', () => {
+ let component: DashboardPieComponent;
+ let fixture: ComponentFixture<DashboardPieComponent>;
+
+ configureTestBed({
+ schemas: [NO_ERRORS_SCHEMA],
+ declarations: [DashboardPieComponent],
+ providers: [CssHelper, DimlessBinaryPipe]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DashboardPieComponent);
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
import { SharedModule } from '~/app/shared/shared.module';
import { CephSharedModule } from '../shared/ceph-shared.module';
import { CardComponent } from './card/card.component';
+import { DashboardPieComponent } from './dashboard-pie/dashboard-pie.component';
import { DashboardComponent } from './dashboard/dashboard.component';
@NgModule({
ReactiveFormsModule
],
- declarations: [DashboardComponent, CardComponent]
+ declarations: [DashboardComponent, CardComponent, DashboardPieComponent]
})
export class NewDashboardModule {}
class="col-sm-3 px-3"
[ngClass]="{'d-flex': flexHeight}">
<ng-container class="ms-4 me-4"
- *ngIf="{osdSettings: osdSettings$ | async, capacity: capacity$ | async} as values">
- <ng-container *ngIf="values.osdSettings && values.capacity">
- <cd-dashboard-pie [data]="{max: values.capacity.total_bytes, current: values.capacity.total_used_raw_bytes}"
- [lowThreshold]="values.osdSettings.nearfull_ratio"
- [highThreshold]="values.osdSettings.full_ratio">
- </cd-dashboard-pie>
- </ng-container>
+ *ngIf="capacity && osdSettings">
+ <cd-dashboard-pie [data]="{max: capacity.total_bytes, current: capacity.total_used_raw_bytes}"
+ [lowThreshold]="osdSettings.nearfull_ratio"
+ [highThreshold]="osdSettings.full_ratio">
+ </cd-dashboard-pie>
</ng-container>
</cd-card>
</div>
import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
import { BehaviorSubject, of } from 'rxjs';
import { ConfigurationService } from '~/app/shared/api/configuration.service';
import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
+import { CssHelper } from '~/app/shared/classes/css-helper';
+import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
import { SummaryService } from '~/app/shared/services/summary.service';
import { configureTestBed } from '~/testing/unit-test-helper';
import { CardComponent } from '../card/card.component';
+import { DashboardPieComponent } from '../dashboard-pie/dashboard-pie.component';
import { DashboardComponent } from './dashboard.component';
export class SummaryServiceMock {
};
configureTestBed({
- imports: [HttpClientTestingModule],
- declarations: [DashboardComponent, CardComponent],
- providers: [{ provide: SummaryService, useClass: SummaryServiceMock }]
+ imports: [RouterTestingModule, HttpClientTestingModule],
+ declarations: [DashboardComponent, CardComponent, DashboardPieComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ CssHelper,
+ DimlessBinaryPipe,
+ { provide: SummaryService, useClass: SummaryServiceMock }
+ ]
});
beforeEach(() => {
-import { Component, OnInit } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import _ from 'lodash';
+import { Observable, Subscription } from 'rxjs';
+import { take } from 'rxjs/operators';
+
+import { ClusterService } from '~/app/shared/api/cluster.service';
import { ConfigurationService } from '~/app/shared/api/configuration.service';
import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
+import { OsdService } from '~/app/shared/api/osd.service';
import { DashboardDetails } from '~/app/shared/models/cd-details';
+import { Permissions } from '~/app/shared/models/permissions';
+import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
+import {
+ FeatureTogglesMap$,
+ FeatureTogglesService
+} from '~/app/shared/services/feature-toggles.service';
import { SummaryService } from '~/app/shared/services/summary.service';
@Component({
{ headers: { Accept: 'application/vnd.ceph.api.v0.1+json' } }
);
}
+
+ getCapacity() {
+ return this.http.get(`${this.baseURL}/capacity`, {});
+ }
}
$body-bg: $white !default;
$body-color: $gray-900 !default;
$body-bg-alt: $gray-200 !default;
-
// Health colors.
$health-color-error: $red !default;
$health-color-healthy: $green !default;
$chart-color-green: $green !default;
$chart-color-gray: #ededed !default;
$chart-color-cyan: $primary-500 !default;
+$chart-color-light-gray: #f0f0f0 !default;
+$chart-color-slight-dark-gray: #d7d7d7 !default;
+$chart-color-dark-gray: #afafaf !default;
+$chart-color-cyan: #73c5c5 !default;
$chart-color-purple: #3c3d99 !default;
+$chart-color-white: #fff !default;
$chart-color-center-text: #151515 !default;
$chart-color-center-text-description: #72767b !default;
$chart-color-tooltip-background: $black !default;
summary: Update the cluster status
tags:
- Cluster
+ /api/cluster/capacity:
+ get:
+ parameters: []
+ responses:
+ '200':
+ content:
+ application/vnd.ceph.api.v1.0+json:
+ type: object
+ description: OK
+ '400':
+ description: Operation exception. Please check the response body for details.
+ '401':
+ description: Unauthenticated access. Please login first.
+ '403':
+ description: Unauthorized access. Please check your permissions.
+ '500':
+ description: Unexpected error. Please check the response body for the stack
+ trace.
+ security:
+ - jwt: []
+ tags:
+ - Cluster
/api/cluster_conf:
get:
parameters: []
# -*- coding: utf-8 -*-
from enum import Enum
+from typing import NamedTuple
from .. import mgr
+class ClusterCapacity(NamedTuple):
+ total_avail_bytes: int
+ total_bytes: int
+ total_used_raw_bytes: int
+
+
class ClusterModel:
class Status(Enum):
If the status is not set, assume it is already fully functional.
"""
return cls(status=mgr.get_store('cluster/status', cls.Status.POST_INSTALLED.name))
+
+ @classmethod
+ def get_capacity(cls) -> ClusterCapacity:
+ df = mgr.get('df')
+ return ClusterCapacity(total_avail_bytes=df['stats']['total_avail_bytes'],
+ total_bytes=df['stats']['total_bytes'],
+ total_used_raw_bytes=df['stats']['total_used_raw_bytes'])._asdict()