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';
27 const BASE_URL = 'pool';
30 selector: 'cd-pool-list',
31 templateUrl: './pool-list.component.html',
34 { provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) }
36 styleUrls: ['./pool-list.component.scss']
38 export class PoolListComponent implements OnInit {
39 @ViewChild(TableComponent)
40 table: TableComponent;
41 @ViewChild('poolUsageTpl')
42 poolUsageTpl: TemplateRef<any>;
44 @ViewChild('poolConfigurationSourceTpl')
45 poolConfigurationSourceTpl: TemplateRef<any>;
48 columns: CdTableColumn[];
49 selection = new CdTableSelection();
51 executingTasks: ExecutingTask[] = [];
52 permissions: Permissions;
53 tableActions: CdTableAction[];
54 viewCacheStatusList: any[];
55 selectionCacheTiers: any[] = [];
58 private poolService: PoolService,
59 private taskWrapper: TaskWrapperService,
60 private authStorageService: AuthStorageService,
61 private taskListService: TaskListService,
62 private modalService: BsModalService,
64 private pgCategoryService: PgCategoryService,
65 private dimlessPipe: DimlessPipe,
66 private urlBuilder: URLBuilderService,
67 public actionLabels: ActionLabelsI18n
69 this.permissions = this.authStorageService.getPermissions();
74 routerLink: () => this.urlBuilder.getCreate(),
75 name: this.actionLabels.CREATE
81 this.urlBuilder.getEdit(encodeURIComponent(this.selection.first().pool_name)),
82 name: this.actionLabels.EDIT
87 click: () => this.deletePoolModal(),
88 name: this.actionLabels.DELETE
97 name: this.i18n('Name'),
99 cellTransformation: CellTemplate.executing
103 name: this.i18n('Type'),
107 prop: 'application_metadata',
108 name: this.i18n('Applications'),
113 name: this.i18n('PG Status'),
115 cellClass: ({ row, column, value }): any => {
116 return this.getPgStatusCellClass(row, column, value);
121 name: this.i18n('Replica Size'),
123 cellClass: 'text-right'
127 name: this.i18n('Last Change'),
129 cellClass: 'text-right'
132 prop: 'erasure_code_profile',
133 name: this.i18n('Erasure Coded Profile'),
138 name: this.i18n('Crush Ruleset'),
141 { name: this.i18n('Usage'), cellTemplate: this.poolUsageTpl, flexGrow: 3 },
143 prop: 'stats.rd_bytes.series',
144 name: this.i18n('Read bytes'),
145 cellTransformation: CellTemplate.sparkline,
149 prop: 'stats.wr_bytes.series',
150 name: this.i18n('Write bytes'),
151 cellTransformation: CellTemplate.sparkline,
155 prop: 'stats.rd.rate',
156 name: this.i18n('Read ops'),
158 pipe: this.dimlessPipe,
159 cellTransformation: CellTemplate.perSecond
162 prop: 'stats.wr.rate',
163 name: this.i18n('Write ops'),
165 pipe: this.dimlessPipe,
166 cellTransformation: CellTemplate.perSecond
170 this.taskListService.init(
171 () => this.poolService.getList(),
173 (pools) => (this.pools = this.transformPoolsData(pools)),
175 this.table.reset(); // Disable loading indicator.
176 this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
178 (task) => task.name.startsWith(`${BASE_URL}/`),
179 (pool, task) => task.metadata['pool_name'] === pool.pool_name,
180 { default: (task: ExecutingTask) => new Pool(task.metadata['pool_name']) }
184 updateSelection(selection: CdTableSelection) {
185 this.selection = selection;
186 this.getSelectionTiers();
190 const name = this.selection.first().pool_name;
191 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
193 itemDescription: 'Pool',
194 submitActionObservable: () =>
195 this.taskWrapper.wrapTaskAroundCall({
196 task: new FinishedTask(`${BASE_URL}/${URLVerbs.DELETE}`, { pool_name: name }),
197 call: this.poolService.delete(name)
203 getPgStatusCellClass(_row, _column, value): object {
206 [`pg-${this.pgCategoryService.getTypeByStates(value)}`]: true
210 transformPoolsData(pools: any) {
211 const requiredStats = ['bytes_used', 'max_avail', 'rd_bytes', 'wr_bytes', 'rd', 'wr'];
212 const emptyStat = { latest: 0, rate: 0, series: [] };
214 _.forEach(pools, (pool: Pool) => {
215 pool['pg_status'] = this.transformPgStatus(pool['pg_status']);
217 _.forEach(requiredStats, (stat) => {
218 stats[stat] = pool.stats && pool.stats[stat] ? pool.stats[stat] : emptyStat;
220 pool['stats'] = stats;
222 ['rd_bytes', 'wr_bytes'].forEach((stat) => {
223 pool.stats[stat].series = pool.stats[stat].series.map((point) => point[1]);
225 pool.cdIsBinary = true;
231 transformPgStatus(pgStatus: any): string {
233 _.forEach(pgStatus, (count, state) => {
234 strings.push(`${count} ${state}`);
237 return strings.join(', ');
240 getPoolDetails(pool: object) {
241 return _.omit(pool, ['cdExecuting', 'cdIsBinary']);
244 getSelectionTiers() {
245 const cacheTierIds = this.selection.hasSingleSelection ? this.selection.first()['tiers'] : [];
246 this.selectionCacheTiers = this.pools.filter((pool) => cacheTierIds.includes(pool.pool));