import { RbdConfigurationListComponent } from '~/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component';
import { PgCategoryService } from '~/app/ceph/shared/pg-category.service';
import { ConfigurationService } from '~/app/shared/api/configuration.service';
+import { ErasureCodeProfileService } from '~/app/shared/api/erasure-code-profile.service';
import { PoolService } from '~/app/shared/api/pool.service';
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { ErasureCodeProfile } from '~/app/shared/models/erasure-code-profile';
import { ExecutingTask } from '~/app/shared/models/executing-task';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
import { ModalService } from '~/app/shared/services/modal.service';
let component: PoolListComponent;
let fixture: ComponentFixture<PoolListComponent>;
let poolService: PoolService;
+ let getECPList: jasmine.Spy;
const getPoolList = (): Pool[] => {
return [Mocks.getPool('a', 0), Mocks.getPool('b', 1), Mocks.getPool('c', 2)];
};
+ const getECPProfiles = (): ErasureCodeProfile[] => {
+ const ecpProfile = new ErasureCodeProfile();
+ ecpProfile.name = 'default';
+ ecpProfile.k = 2;
+ ecpProfile.m = 1;
+
+ return [ecpProfile];
+ };
configureTestBed({
declarations: [PoolListComponent, PoolDetailsComponent, RbdConfigurationListComponent],
component.permissions.pool.read = true;
poolService = TestBed.inject(PoolService);
spyOn(poolService, 'getList').and.callFake(() => of(getPoolList()));
+ getECPList = spyOn(TestBed.inject(ErasureCodeProfileService), 'list');
+ getECPList.and.returnValue(of(getECPProfiles()));
fixture.detectChanges();
});
wr: { latest: 0, rate: 0, rates: [] },
wr_bytes: { latest: 0, rate: 0, rates: [] }
},
- usage: 0
+ usage: 0,
+ data_protection: 'replica: ×3'
}),
o
)
pool = Mocks.getPool('a', 0);
});
- it('transforms pools data correctly', () => {
+ it('transforms replicated pools data correctly', () => {
pool = _.merge(pool, {
stats: {
bytes_used: { latest: 5, rate: 0, rates: [] },
percent_used: { latest: 0.25, rate: 0, rates: [] },
rd_bytes: { latest: 6, rate: 4, rates: [2, 6] }
},
- usage: 0.25
+ usage: 0.25,
+ data_protection: 'replica: ×3'
+ })
+ );
+ });
+
+ it('transforms erasure pools data correctly', () => {
+ pool.type = 'erasure';
+ pool.erasure_code_profile = 'default';
+ component.ecProfileList = getECPProfiles();
+
+ expect(component.transformPoolsData([pool])).toEqual(
+ getPoolData({
+ type: 'erasure',
+ erasure_code_profile: 'default',
+ data_protection: 'EC: 2+1'
})
);
});
pg_num: 32,
pg_num_target: 16,
pg_placement_num: 32,
- pg_placement_num_target: 16
+ pg_placement_num_target: 16,
+ data_protection: 'replica: ×3'
})
);
});
pg_num: 32,
pg_num_target: 16,
pg_placement_num: 32,
- pg_placement_num_target: 16
+ pg_placement_num_target: 16,
+ data_protection: 'replica: ×3'
})
);
});
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import _ from 'lodash';
+import { mergeMap } from 'rxjs/operators';
import { PgCategoryService } from '~/app/ceph/shared/pg-category.service';
import { ConfigurationService } from '~/app/shared/api/configuration.service';
+import { ErasureCodeProfileService } from '~/app/shared/api/erasure-code-profile.service';
import { PoolService } from '~/app/shared/api/pool.service';
import { ListWithDetails } from '~/app/shared/classes/list-with-details.class';
import { TableStatusViewCache } from '~/app/shared/classes/table-status-view-cache';
import { CdTableAction } from '~/app/shared/models/cd-table-action';
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
+import { ErasureCodeProfile } from '~/app/shared/models/erasure-code-profile';
import { ExecutingTask } from '~/app/shared/models/executing-task';
import { FinishedTask } from '~/app/shared/models/finished-task';
import { Permissions } from '~/app/shared/models/permissions';
tableStatus = new TableStatusViewCache();
cacheTiers: any[] = [];
monAllowPoolDelete = false;
+ ecProfileList: ErasureCodeProfile[];
constructor(
private poolService: PoolService,
private taskWrapper: TaskWrapperService,
+ private ecpService: ErasureCodeProfileService,
private authStorageService: AuthStorageService,
public taskListService: TaskListService,
private modalService: ModalService,
cellTransformation: CellTemplate.executing
},
{
- prop: 'type',
- name: $localize`Type`,
- flexGrow: 2
+ prop: 'data_protection',
+ name: $localize`Data Protection`,
+ cellTransformation: CellTemplate.badge,
+ customTemplateConfig: {
+ class: 'badge-background-gray'
+ },
+ flexGrow: 1.3
},
{
prop: 'application_metadata',
name: $localize`Applications`,
- flexGrow: 3
+ cellTransformation: CellTemplate.badge,
+ customTemplateConfig: {
+ class: 'badge-background-primary'
+ },
+ flexGrow: 1.5
},
{
prop: 'pg_status',
name: $localize`PG Status`,
- flexGrow: 3,
+ flexGrow: 1.2,
cellClass: ({ row, column, value }): any => {
return this.getPgStatusCellClass(row, column, value);
}
},
- {
- prop: 'size',
- name: $localize`Replica Size`,
- flexGrow: 2,
- cellClass: 'text-right'
- },
- {
- prop: 'erasure_code_profile',
- name: $localize`Erasure Coded Profile`,
- flexGrow: 2
- },
{
prop: 'crush_rule',
name: $localize`Crush Ruleset`,
- flexGrow: 3
+ isHidden: true,
+ flexGrow: 2
},
{
name: $localize`Usage`,
prop: 'usage',
cellTemplate: this.poolUsageTpl,
- flexGrow: 3
+ flexGrow: 1.2
},
{
prop: 'stats.rd_bytes.rates',
comparator: (_valueA: any, _valueB: any, rowA: Pool, rowB: Pool) =>
compare('stats.rd_bytes.latest', rowA, rowB),
cellTransformation: CellTemplate.sparkline,
- flexGrow: 3
+ flexGrow: 1.5
},
{
prop: 'stats.wr_bytes.rates',
comparator: (_valueA: any, _valueB: any, rowA: Pool, rowB: Pool) =>
compare('stats.wr_bytes.latest', rowA, rowB),
cellTransformation: CellTemplate.sparkline,
- flexGrow: 3
+ flexGrow: 1.5
},
{
prop: 'stats.rd.rate',
];
this.taskListService.init(
- () => this.poolService.getList(),
+ () =>
+ this.ecpService.list().pipe(
+ mergeMap((ecProfileList: ErasureCodeProfile[]) => {
+ this.ecProfileList = ecProfileList;
+ return this.poolService.getList();
+ })
+ ),
undefined,
(pools) => {
this.pools = this.transformPoolsData(pools);
};
}
+ getErasureCodeProfile(erasureCodeProfile: string) {
+ let ecpInfo = '';
+ _.forEach(this.ecProfileList, (ecpKey) => {
+ if (ecpKey['name'] === erasureCodeProfile) {
+ ecpInfo = `EC: ${ecpKey['k']}+${ecpKey['m']}`;
+ }
+ });
+ return ecpInfo;
+ }
+
transformPoolsData(pools: any) {
const requiredStats = [
'bytes_used',
pool.stats[stat].rates = pool.stats[stat].rates.map((point: any) => point[1]);
});
pool.cdIsBinary = true;
+
+ if (pool['type'] === 'erasure') {
+ const erasureCodeProfile = pool['erasure_code_profile'];
+ pool['data_protection'] = this.getErasureCodeProfile(erasureCodeProfile);
+ }
+ if (pool['type'] === 'replicated') {
+ pool['data_protection'] = `replica: ×${pool['size']}`;
+ }
});
return pools;