From c7b82c3999f8e1b8342aedf07aacf2863c2dff16 Mon Sep 17 00:00:00 2001 From: Tatjana Dehler Date: Thu, 18 Oct 2018 14:57:39 +0200 Subject: [PATCH] mgr/dashboard: add OSD recovery speed form Add a form to set the OSD recovery speed. There are three predefined priorities available: 'Low', 'Default' and 'High'. By setting the priority the config options 'osd_max_backfills', 'osd_recovery_max_active', 'osd_recovery_max_single_start', 'osd_recovery_sleep' will be updated with predefined values. It's also possible to set custom values. Fixes: https://tracker.ceph.com/issues/35540 Signed-off-by: Tatjana Dehler --- .../src/app/ceph/cluster/cluster.module.ts | 5 +- .../osd/osd-list/osd-list.component.html | 11 +- .../osd/osd-list/osd-list.component.ts | 5 + .../osd-recv-speed-modal.component.html | 82 ++++ .../osd-recv-speed-modal.component.scss | 0 .../osd-recv-speed-modal.component.spec.ts | 364 ++++++++++++++++++ .../osd-recv-speed-modal.component.ts | 180 +++++++++ .../osd-recv-speed-modal.priorities.ts | 45 +++ .../app/shared/api/configuration.service.ts | 4 + .../frontend/src/locale/messages.xlf | 173 +++++++-- 10 files changed, 827 insertions(+), 42 deletions(-) create mode 100755 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html create mode 100755 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss create mode 100755 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts create mode 100755 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts create mode 100755 src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.priorities.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts index bf2177d9878fd..2adb5a015af93 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts @@ -24,6 +24,7 @@ import { OsdDetailsComponent } from './osd/osd-details/osd-details.component'; import { OsdFlagsModalComponent } from './osd/osd-flags-modal/osd-flags-modal.component'; import { OsdListComponent } from './osd/osd-list/osd-list.component'; import { OsdPerformanceHistogramComponent } from './osd/osd-performance-histogram/osd-performance-histogram.component'; +import { OsdRecvSpeedModalComponent } from './osd/osd-recv-speed-modal/osd-recv-speed-modal.component'; import { OsdReweightModalComponent } from './osd/osd-reweight-modal/osd-reweight-modal.component'; import { OsdScrubModalComponent } from './osd/osd-scrub-modal/osd-scrub-modal.component'; @@ -32,6 +33,7 @@ import { OsdScrubModalComponent } from './osd/osd-scrub-modal/osd-scrub-modal.co OsdDetailsComponent, OsdScrubModalComponent, OsdFlagsModalComponent, + OsdRecvSpeedModalComponent, OsdReweightModalComponent ], imports: [ @@ -62,7 +64,8 @@ import { OsdScrubModalComponent } from './osd/osd-scrub-modal/osd-scrub-modal.co ConfigurationFormComponent, OsdReweightModalComponent, CrushmapComponent, - LogsComponent + LogsComponent, + OsdRecvSpeedModalComponent ] }) export class ClusterModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html index 206de6d3ec2b3..d743bf188798c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html @@ -20,7 +20,16 @@ - Set Cluster-wide OSD Flags + Set Cluster-wide Flags + + + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts index e685e1de85a85..261d8e5e13ef9 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.ts @@ -16,6 +16,7 @@ import { Permissions } from '../../../../shared/models/permissions'; import { DimlessBinaryPipe } from '../../../../shared/pipes/dimless-binary.pipe'; import { AuthStorageService } from '../../../../shared/services/auth-storage.service'; import { OsdFlagsModalComponent } from '../osd-flags-modal/osd-flags-modal.component'; +import { OsdRecvSpeedModalComponent } from '../osd-recv-speed-modal/osd-recv-speed-modal.component'; import { OsdReweightModalComponent } from '../osd-reweight-modal/osd-reweight-modal.component'; import { OsdScrubModalComponent } from '../osd-scrub-modal/osd-scrub-modal.component'; @@ -301,4 +302,8 @@ export class OsdListComponent implements OnInit { }); }); } + + configureQosParamsAction() { + this.bsModalRef = this.modalService.show(OsdRecvSpeedModalComponent, {}); + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html new file mode 100755 index 0000000000000..7a7dc9bd04e18 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html @@ -0,0 +1,82 @@ + + OSD Recovery Priority + + +
+ + +
+
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.scss new file mode 100755 index 0000000000000..e69de29bb2d1d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts new file mode 100755 index 0000000000000..3336ed8e5c0de --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.spec.ts @@ -0,0 +1,364 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; + +import * as _ from 'lodash'; +import { ToastModule } from 'ng2-toastr'; +import { BsModalRef, ModalModule } from 'ngx-bootstrap/modal'; +import { of } from 'rxjs'; + +import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper'; +import { ConfigurationService } from '../../../../shared/api/configuration.service'; +import { SharedModule } from '../../../../shared/shared.module'; +import { OsdRecvSpeedModalComponent } from './osd-recv-speed-modal.component'; + +describe('OsdRecvSpeedModalComponent', () => { + let component: OsdRecvSpeedModalComponent; + let fixture: ComponentFixture; + let configService: ConfigurationService; + + configureTestBed({ + imports: [ + HttpClientTestingModule, + ModalModule.forRoot(), + ReactiveFormsModule, + SharedModule, + ToastModule.forRoot() + ], + declarations: [OsdRecvSpeedModalComponent], + providers: [BsModalRef, i18nProviders] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OsdRecvSpeedModalComponent); + component = fixture.componentInstance; + configService = TestBed.get(ConfigurationService); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('setPriority', () => { + it('should prepare the form for a custom priority', () => { + const customPriority = { + name: 'custom', + text: 'Custom', + values: { + osd_max_backfills: 1, + osd_recovery_max_active: 4, + osd_recovery_max_single_start: 1, + osd_recovery_sleep: 1 + } + }; + + component.setPriority(customPriority); + + const customInPriorities = _.find(component.priorities, (p) => { + return p.name === 'custom'; + }); + + expect(customInPriorities).not.toBeNull(); + expect(component.osdRecvSpeedForm.getValue('priority')).toBe('custom'); + expect(component.osdRecvSpeedForm.getValue('osd_max_backfills')).toBe(1); + expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_active')).toBe(4); + expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_single_start')).toBe(1); + expect(component.osdRecvSpeedForm.getValue('osd_recovery_sleep')).toBe(1); + }); + + it('should prepare the form for a none custom priority', () => { + const lowPriority = { + name: 'low', + text: 'Low', + values: { + osd_max_backfills: 1, + osd_recovery_max_active: 1, + osd_recovery_max_single_start: 1, + osd_recovery_sleep: 0.5 + } + }; + + component.setPriority(lowPriority); + + const customInPriorities = _.find(component.priorities, (p) => { + return p.name === 'custom'; + }); + + expect(customInPriorities).toBeUndefined(); + expect(component.osdRecvSpeedForm.getValue('priority')).toBe('low'); + expect(component.osdRecvSpeedForm.getValue('osd_max_backfills')).toBe(1); + expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_active')).toBe(1); + expect(component.osdRecvSpeedForm.getValue('osd_recovery_max_single_start')).toBe(1); + expect(component.osdRecvSpeedForm.getValue('osd_recovery_sleep')).toBe(0.5); + }); + }); + + describe('getStoredPriority', () => { + const configOptionsLow = [ + { + name: 'osd_max_backfills', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_max_active', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_max_single_start', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_sleep', + value: [ + { + section: 'osd', + value: '0.5' + } + ] + } + ]; + + const configOptionsDefault = [ + { + name: 'osd_max_backfills', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_max_active', + value: [ + { + section: 'osd', + value: '3' + } + ] + }, + { + name: 'osd_recovery_max_single_start', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_sleep', + value: [ + { + section: 'osd', + value: '0' + } + ] + } + ]; + + const configOptionsHigh = [ + { + name: 'osd_max_backfills', + value: [ + { + section: 'osd', + value: '4' + } + ] + }, + { + name: 'osd_recovery_max_active', + value: [ + { + section: 'osd', + value: '4' + } + ] + }, + { + name: 'osd_recovery_max_single_start', + value: [ + { + section: 'osd', + value: '4' + } + ] + }, + { + name: 'osd_recovery_sleep', + value: [ + { + section: 'osd', + value: '0' + } + ] + } + ]; + + const configOptionsCustom = [ + { + name: 'osd_max_backfills', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_max_active', + value: [ + { + section: 'osd', + value: '2' + } + ] + }, + { + name: 'osd_recovery_max_single_start', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_sleep', + value: [ + { + section: 'osd', + value: '0' + } + ] + } + ]; + + const configOptionsIncomplete = [ + { + name: 'osd_max_backfills', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_max_single_start', + value: [ + { + section: 'osd', + value: '1' + } + ] + }, + { + name: 'osd_recovery_sleep', + value: [ + { + section: 'osd', + value: '0' + } + ] + } + ]; + + it('should return priority "low" if the config option values have been set accordingly', fakeAsync(() => { + spyOn(configService, 'get').and.callFake((configOptionName: string) => { + const result = _.find(configOptionsLow, (configOption) => { + return configOption.name === configOptionName; + }); + return of(result); + }); + + component.getStoredPriority((priority) => { + expect(priority.name).toBe('low'); + }); + tick(); + + expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy(); + })); + + it('should return priority "default" if the config option values have been set accordingly', fakeAsync(() => { + spyOn(configService, 'get').and.callFake((configOptionName: string) => { + const result = _.find(configOptionsDefault, (configOption) => { + return configOption.name === configOptionName; + }); + return of(result); + }); + + component.getStoredPriority((priority) => { + expect(priority.name).toBe('default'); + }); + tick(); + + expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy(); + })); + + it('should return priority "high" if the config option values have been set accordingly', fakeAsync(() => { + spyOn(configService, 'get').and.callFake((configOptionName: string) => { + const result = _.find(configOptionsHigh, (configOption) => { + return configOption.name === configOptionName; + }); + return of(result); + }); + + component.getStoredPriority((priority) => { + expect(priority.name).toBe('high'); + }); + tick(); + + expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy(); + })); + + it('should return priority "custom" if the config option values do not match any priority', fakeAsync(() => { + spyOn(configService, 'get').and.callFake((configOptionName: string) => { + const result = _.find(configOptionsCustom, (configOption) => { + return configOption.name === configOptionName; + }); + return of(result); + }); + + component.getStoredPriority((priority) => { + expect(priority.name).toBe('custom'); + }); + tick(); + + expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeTruthy(); + })); + + it('should return no priority if the config option values are incomplete', fakeAsync(() => { + spyOn(configService, 'get').and.callFake((configOptionName: string) => { + const result = _.find(configOptionsIncomplete, (configOption) => { + return configOption.name === configOptionName; + }); + return of(result); + }); + + component.getStoredPriority((priority) => { + expect(priority.name).toBeNull(); + }); + tick(); + + expect(component.osdRecvSpeedForm.getValue('customizePriority')).toBeFalsy(); + })); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts new file mode 100755 index 0000000000000..948bea22b9cf9 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts @@ -0,0 +1,180 @@ +import { Component, OnInit } from '@angular/core'; +import { FormControl, Validators } from '@angular/forms'; + +import { I18n } from '@ngx-translate/i18n-polyfill'; +import * as _ from 'lodash'; +import { BsModalRef } from 'ngx-bootstrap/modal'; +import { forkJoin as observableForkJoin, of } from 'rxjs'; +import { mergeMap } from 'rxjs/operators'; + +import { ConfigurationService } from '../../../../shared/api/configuration.service'; +import { NotificationType } from '../../../../shared/enum/notification-type.enum'; +import { CdFormGroup } from '../../../../shared/forms/cd-form-group'; +import { NotificationService } from '../../../../shared/services/notification.service'; +import { OsdRecvSpeedModalPriorities } from './osd-recv-speed-modal.priorities'; + +@Component({ + selector: 'cd-osd-recv-speed-modal', + templateUrl: './osd-recv-speed-modal.component.html', + styleUrls: ['./osd-recv-speed-modal.component.scss'] +}) +export class OsdRecvSpeedModalComponent implements OnInit { + osdRecvSpeedForm: CdFormGroup; + priorities = OsdRecvSpeedModalPriorities.KNOWN_PRIORITIES; + priorityAttrs = []; + + constructor( + public bsModalRef: BsModalRef, + private configService: ConfigurationService, + private notificationService: NotificationService, + private i18n: I18n + ) { + this.osdRecvSpeedForm = new CdFormGroup({ + priority: new FormControl(null, { validators: [Validators.required] }), + customizePriority: new FormControl(false) + }); + this.priorityAttrs = [ + { + name: 'osd_max_backfills', + text: this.i18n('Max Backfills') + }, + { + name: 'osd_recovery_max_active', + text: this.i18n('Recovery Max Active') + }, + { + name: 'osd_recovery_max_single_start', + text: this.i18n('Recovery Max Single Start') + }, + { + name: 'osd_recovery_sleep', + text: this.i18n('Recovery Sleep') + } + ]; + + this.priorityAttrs.forEach((attr) => { + this.osdRecvSpeedForm.addControl( + attr.name, + new FormControl(null, { validators: [Validators.required] }) + ); + }); + } + + ngOnInit() { + this.getStoredPriority((priority) => { + this.setPriority(priority); + }); + } + + setPriority(priority: any) { + const customPriority = _.find(this.priorities, (p) => { + return p.name === 'custom'; + }); + + if (priority.name === 'custom') { + if (!customPriority) { + this.priorities.push(priority); + } + } else { + if (customPriority) { + this.priorities.splice(this.priorities.indexOf(customPriority), 1); + } + } + + this.osdRecvSpeedForm.controls.priority.setValue(priority.name); + Object.entries(priority.values).forEach(([name, value]) => { + this.osdRecvSpeedForm.controls[name].setValue(value); + }); + } + + onCustomizePriorityChange() { + if (this.osdRecvSpeedForm.getValue('customizePriority')) { + const values = {}; + this.priorityAttrs.forEach((attr) => { + values[attr.name] = this.osdRecvSpeedForm.getValue(attr.name); + }); + const customPriority = { + name: 'custom', + text: this.i18n('Custom'), + values: values + }; + this.setPriority(customPriority); + } else { + this.setPriority(this.priorities[0]); + } + } + + getStoredPriority(callbackFn: Function) { + const observables = []; + this.priorityAttrs.forEach((configName) => { + observables.push(this.configService.get(configName.name)); + }); + + observableForkJoin(observables) + .pipe( + mergeMap((configOptions) => { + const result = {}; + configOptions.forEach((configOption) => { + if (configOption && 'value' in configOption) { + configOption.value.forEach((value) => { + if (value['section'] === 'osd') { + result[configOption.name] = Number(value.value); + } + }); + } + }); + return of(result); + }) + ) + .subscribe((resp) => { + const priority = _.find(this.priorities, (p) => { + return _.isEqual(p.values, resp); + }); + + this.osdRecvSpeedForm.controls.customizePriority.setValue(false); + + if (priority) { + return callbackFn(priority); + } + + if (Object.entries(resp).length === 4) { + this.osdRecvSpeedForm.controls.customizePriority.setValue(true); + return callbackFn(Object({ name: 'custom', text: this.i18n('Custom'), values: resp })); + } + + return callbackFn(this.priorities[0]); + }); + } + + onPriorityChange(selectedPriorityName) { + const selectedPriority = + _.find(this.priorities, (p) => { + return p.name === selectedPriorityName; + }) || this.priorities[0]; + + this.setPriority(selectedPriority); + } + + submitAction() { + const options = {}; + this.priorityAttrs.forEach((attr) => { + options[attr.name] = { section: 'osd', value: this.osdRecvSpeedForm.getValue(attr.name) }; + }); + + this.configService.bulkCreate({ options: options }).subscribe( + () => { + this.notificationService.show( + NotificationType.success, + this.i18n('OSD recovery speed priority "{{value}}" was set successfully.', { + value: this.osdRecvSpeedForm.getValue('priority') + }), + this.i18n('OSD recovery speed priority') + ); + this.bsModalRef.hide(); + }, + () => { + this.bsModalRef.hide(); + } + ); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.priorities.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.priorities.ts new file mode 100755 index 0000000000000..7b1bacdfb697e --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.priorities.ts @@ -0,0 +1,45 @@ +export class OsdRecvSpeedModalPriorities { + public static KNOWN_PRIORITIES = [ + // TODO: I18n + { + name: null, + text: '-- Select the priority --', + values: { + osd_max_backfills: null, + osd_recovery_max_active: null, + osd_recovery_max_single_start: null, + osd_recovery_sleep: null + } + }, + { + name: 'low', + text: 'Low', + values: { + osd_max_backfills: 1, + osd_recovery_max_active: 1, + osd_recovery_max_single_start: 1, + osd_recovery_sleep: 0.5 + } + }, + { + name: 'default', + text: 'Default', + values: { + osd_max_backfills: 1, + osd_recovery_max_active: 3, + osd_recovery_max_single_start: 1, + osd_recovery_sleep: 0 + } + }, + { + name: 'high', + text: 'High', + values: { + osd_max_backfills: 4, + osd_recovery_max_active: 4, + osd_recovery_max_single_start: 4, + osd_recovery_sleep: 0 + } + } + ]; +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts index 6e7a98d8f31ab..a977a17d180e7 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/configuration.service.ts @@ -21,4 +21,8 @@ export class ConfigurationService { create(configOption: ConfigFormCreateRequestModel) { return this.http.post('api/cluster_conf/', configOption); } + + bulkCreate(configOptions: Object) { + return this.http.put('api/cluster_conf', configOptions); + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf index 11343488773b1..7ffbb43fdae9e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf +++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf @@ -361,6 +361,10 @@ app/ceph/block/rbd-form/rbd-form.component.html 175 + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 31 + app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html 18 @@ -759,7 +763,7 @@ app/ceph/cluster/osd/osd-list/osd-list.component.html - 50 + 59 app/ceph/pool/pool-list/pool-list.component.html @@ -859,6 +863,10 @@ app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.html 38 + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 77 + app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html 34 @@ -903,10 +911,70 @@ app/ceph/cluster/osd/osd-flags-modal/osd-flags-modal.component.html 34 + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 73 + app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html 21 + + OSD Recovery Priority + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 3 + + + Priority + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 16 + + + Customize priority values + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 44 + + + This field is required! + + app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html + 65 + + + app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html + 34 + + + app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html + 68 + + + app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html + 92 + + + app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html + 118 + + + app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html + 166 + + + app/ceph/pool/pool-form/pool-form.component.html + 40 + + + app/ceph/pool/pool-form/pool-form.component.html + 69 + + + app/ceph/pool/pool-form/pool-form.component.html + 95 + Reweight OSD @@ -950,12 +1018,18 @@ app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html 13 - - Set Cluster-wide OSD Flags + + Set Cluster-wide Flags app/ceph/cluster/osd/osd-list/osd-list.component.html 23 + + Set Cluster-wide Recovery Priority + + app/ceph/cluster/osd/osd-list/osd-list.component.html + 32 + OSDs List @@ -967,20 +1041,20 @@ if you proceed. app/ceph/cluster/osd/osd-list/osd-list.component.html - 65 + 74 The OSD is not safe to destroy! app/ceph/cluster/osd/osd-list/osd-list.component.html - 74 + 83 OSD will be if you proceed. app/ceph/cluster/osd/osd-list/osd-list.component.html - 76 + 85 Health @@ -1000,40 +1074,6 @@ app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html 3 - - This field is required! - - app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html - 34 - - - app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html - 68 - - - app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html - 92 - - - app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html - 118 - - - app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form.component.html - 166 - - - app/ceph/pool/pool-form/pool-form.component.html - 40 - - - app/ceph/pool/pool-form/pool-form.component.html - 69 - - - app/ceph/pool/pool-form/pool-form.component.html - 95 - The chosen erasure code profile name is already in use. @@ -3843,6 +3883,59 @@ 1 + + Max Backfills + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + + Recovery Max Active + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + + Recovery Max Single Start + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + + Recovery Sleep + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + + Custom + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + + OSD recovery speed priority "" was set successfully. + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + + + OSD recovery speed priority + + src/app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.ts + 1 + + was initialized in the following OSD: -- 2.39.5