1 import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
3 import { I18n } from '@ngx-translate/i18n-polyfill';
4 import * as _ from 'lodash';
5 import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
7 import { PoolService } from '../../../shared/api/pool.service';
8 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
9 import { ActionLabelsI18n, URLVerbs } from '../../../shared/constants/app.constants';
10 import { TableComponent } from '../../../shared/datatable/table/table.component';
11 import { CellTemplate } from '../../../shared/enum/cell-template.enum';
12 import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
13 import { CdTableAction } from '../../../shared/models/cd-table-action';
14 import { CdTableColumn } from '../../../shared/models/cd-table-column';
15 import { CdTableSelection } from '../../../shared/models/cd-table-selection';
16 import { ExecutingTask } from '../../../shared/models/executing-task';
17 import { FinishedTask } from '../../../shared/models/finished-task';
18 import { Permissions } from '../../../shared/models/permissions';
19 import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
20 import { AuthStorageService } from '../../../shared/services/auth-storage.service';
21 import { TaskListService } from '../../../shared/services/task-list.service';
22 import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
23 import { URLBuilderService } from '../../../shared/services/url-builder.service';
24 import { PgCategoryService } from '../../shared/pg-category.service';
25 import { Pool } from '../pool';
26 import { PoolStats } from '../pool-stat';
28 const BASE_URL = 'pool';
31 selector: 'cd-pool-list',
32 templateUrl: './pool-list.component.html',
35 { provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }
37 styleUrls: ['./pool-list.component.scss']
39 export class PoolListComponent implements OnInit {
40 @ViewChild(TableComponent)
41 table: TableComponent;
42 @ViewChild('poolUsageTpl')
43 poolUsageTpl: TemplateRef<any>;
45 @ViewChild('poolConfigurationSourceTpl')
46 poolConfigurationSourceTpl: TemplateRef<any>;
49 columns: CdTableColumn[];
50 selection = new CdTableSelection();
52 executingTasks: ExecutingTask[] = [];
53 permissions: Permissions;
54 tableActions: CdTableAction[];
55 viewCacheStatusList: any[];
56 selectionCacheTiers: any[] = [];
59 private poolService: PoolService,
60 private taskWrapper: TaskWrapperService,
61 private authStorageService: AuthStorageService,
62 private taskListService: TaskListService,
63 private modalService: BsModalService,
65 private pgCategoryService: PgCategoryService,
66 private dimlessPipe: DimlessPipe,
67 private urlBuilder: URLBuilderService,
68 public actionLabels: ActionLabelsI18n
70 this.permissions = this.authStorageService.getPermissions();
75 routerLink: () => this.urlBuilder.getCreate(),
76 name: this.actionLabels.CREATE
82 this.urlBuilder.getEdit(encodeURIComponent(this.selection.first().pool_name)),
83 name: this.actionLabels.EDIT
88 click: () => this.deletePoolModal(),
89 name: this.actionLabels.DELETE
98 name: this.i18n('Name'),
100 cellTransformation: CellTemplate.executing
104 name: this.i18n('Type'),
108 prop: 'application_metadata',
109 name: this.i18n('Applications'),
114 name: this.i18n('PG Status'),
116 cellClass: ({ row, column, value }): any => {
117 return this.getPgStatusCellClass(row, column, value);
122 name: this.i18n('Replica Size'),
124 cellClass: 'text-right'
128 name: this.i18n('Last Change'),
130 cellClass: 'text-right'
133 prop: 'erasure_code_profile',
134 name: this.i18n('Erasure Coded Profile'),
139 name: this.i18n('Crush Ruleset'),
143 name: this.i18n('Usage'),
145 cellTemplate: this.poolUsageTpl,
149 prop: 'stats.rd_bytes.series',
150 name: this.i18n('Read bytes'),
151 cellTransformation: CellTemplate.sparkline,
155 prop: 'stats.wr_bytes.series',
156 name: this.i18n('Write bytes'),
157 cellTransformation: CellTemplate.sparkline,
161 prop: 'stats.rd.rate',
162 name: this.i18n('Read ops'),
164 pipe: this.dimlessPipe,
165 cellTransformation: CellTemplate.perSecond
168 prop: 'stats.wr.rate',
169 name: this.i18n('Write ops'),
171 pipe: this.dimlessPipe,
172 cellTransformation: CellTemplate.perSecond
176 this.taskListService.init(
177 () => this.poolService.getList(),
179 (pools) => (this.pools = this.transformPoolsData(pools)),
181 this.table.reset(); // Disable loading indicator.
182 this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
184 (task) => task.name.startsWith(`${BASE_URL}/`),
185 (pool, task) => task.metadata['pool_name'] === pool.pool_name,
186 { default: (task: ExecutingTask) => new Pool(task.metadata['pool_name']) }
190 updateSelection(selection: CdTableSelection) {
191 this.selection = selection;
192 this.getSelectionTiers();
196 const name = this.selection.first().pool_name;
197 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
199 itemDescription: 'Pool',
200 submitActionObservable: () =>
201 this.taskWrapper.wrapTaskAroundCall({
202 task: new FinishedTask(`${BASE_URL}/${URLVerbs.DELETE}`, { pool_name: name }),
203 call: this.poolService.delete(name)
209 getPgStatusCellClass(_row, _column, value): object {
212 [`pg-${this.pgCategoryService.getTypeByStates(value)}`]: true
216 transformPoolsData(pools: any) {
217 const requiredStats = ['bytes_used', 'max_avail', 'rd_bytes', 'wr_bytes', 'rd', 'wr'];
218 const emptyStat = { latest: 0, rate: 0, series: [] };
220 _.forEach(pools, (pool: Pool) => {
221 pool['pg_status'] = this.transformPgStatus(pool['pg_status']);
222 const stats: PoolStats = {};
223 _.forEach(requiredStats, (stat) => {
224 stats[stat] = pool.stats && pool.stats[stat] ? pool.stats[stat] : emptyStat;
226 pool['stats'] = stats;
227 const avail = stats.bytes_used.latest + stats.max_avail.latest;
228 pool['usage'] = avail > 0 ? stats.bytes_used.latest / avail : avail;
230 ['rd_bytes', 'wr_bytes'].forEach((stat) => {
231 pool.stats[stat].series = pool.stats[stat].series.map((point) => point[1]);
233 pool.cdIsBinary = true;
239 transformPgStatus(pgStatus: any): string {
241 _.forEach(pgStatus, (count, state) => {
242 strings.push(`${count} ${state}`);
245 return strings.join(', ');
248 getPoolDetails(pool: object) {
249 return _.omit(pool, ['cdExecuting', 'cdIsBinary']);
252 getSelectionTiers() {
253 const cacheTierIds = this.selection.hasSingleSelection ? this.selection.first()['tiers'] : [];
254 this.selectionCacheTiers = this.pools.filter((pool) => cacheTierIds.includes(pool.pool));