1 import { Component, OnInit, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
2 import { BehaviorSubject, forkJoin, Observable, of } from 'rxjs';
3 import { catchError, map, switchMap, tap } from 'rxjs/operators';
4 import { GatewayGroup, NvmeofService } from '~/app/shared/api/nvmeof.service';
5 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
6 import { TableComponent } from '~/app/shared/datatable/table/table.component';
7 import { CdTableAction } from '~/app/shared/models/cd-table-action';
8 import { CdTableColumn } from '~/app/shared/models/cd-table-column';
9 import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
10 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
11 import { Permission } from '~/app/shared/models/permissions';
12 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
13 import { Icons, IconSize } from '~/app/shared/enum/icons.enum';
14 import { NvmeofGatewayGroup } from '~/app/shared/models/nvmeof';
15 import { CephServiceSpec } from '~/app/shared/models/service.interface';
16 import { ModalCdsService } from '~/app/shared/services/modal-cds.service';
17 import { CephServiceService } from '~/app/shared/api/ceph-service.service';
18 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
19 import { DeleteConfirmationModalComponent } from '~/app/shared/components/delete-confirmation-modal/delete-confirmation-modal.component';
20 import { FinishedTask } from '~/app/shared/models/finished-task';
21 import { DeletionImpact } from '~/app/shared/enum/delete-confirmation-modal-impact.enum';
22 import { NotificationService } from '~/app/shared/services/notification.service';
23 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
26 selector: 'cd-nvmeof-gateway-group',
27 templateUrl: './nvmeof-gateway-group.component.html',
28 styleUrls: ['./nvmeof-gateway-group.component.scss'],
30 encapsulation: ViewEncapsulation.None
32 export class NvmeofGatewayGroupComponent implements OnInit {
33 @ViewChild(TableComponent, { static: true })
34 table: TableComponent;
36 @ViewChild('dateTpl', { static: true })
37 dateTpl: TemplateRef<any>;
39 @ViewChild('gatewayStatusTpl', { static: true })
40 gatewayStatusTpl: TemplateRef<any>;
42 @ViewChild('deleteTpl', { static: true })
43 deleteTpl: TemplateRef<any>;
45 permission: Permission;
46 tableActions: CdTableAction[];
47 columns: CdTableColumn[] = [];
48 selection: CdTableSelection = new CdTableSelection();
49 gatewayGroup$: Observable<CephServiceSpec[]>;
50 subject = new BehaviorSubject<CephServiceSpec[]>([]);
51 context: CdTableFetchDataContext;
52 gatewayGroupName: string;
53 subsystemCount: number;
61 public actionLabels: ActionLabelsI18n,
62 private authStorageService: AuthStorageService,
63 private nvmeofService: NvmeofService,
64 public modalService: ModalCdsService,
65 private cephServiceService: CephServiceService,
66 public taskWrapper: TaskWrapperService,
67 private notificationService: NotificationService
71 this.permission = this.authStorageService.getPermissions().nvmeof;
75 name: $localize`Name`,
79 name: $localize`Gateways`,
81 cellTemplate: this.gatewayStatusTpl
84 name: $localize`Subsystems`,
85 prop: 'subSystemCount'
88 name: $localize`Created on`,
90 cellTemplate: this.dateTpl
94 const createAction: CdTableAction = {
97 name: this.actionLabels.CREATE,
98 canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
101 const deleteAction: CdTableAction = {
102 permission: 'delete',
104 click: () => this.deleteGatewayGroupModal(),
105 name: this.actionLabels.DELETE,
106 canBePrimary: (selection: CdTableSelection) => selection.hasMultiSelection
108 this.tableActions = [createAction, deleteAction];
109 this.gatewayGroup$ = this.subject.pipe(
111 this.nvmeofService.listGatewayGroups().pipe(
112 switchMap((gatewayGroups: GatewayGroup[][]) => {
113 const groups = gatewayGroups?.[0] ?? [];
114 if (groups.length === 0) {
118 groups.map((group: NvmeofGatewayGroup) => {
119 const isRunning = (group.status?.running ?? 0) > 0;
120 const subsystemsObservable = isRunning
122 .listSubsystems(group.spec.group)
123 .pipe(catchError(() => of([])))
126 return subsystemsObservable.pipe(
129 name: group.spec?.group,
131 running: group.status?.running ?? 0,
132 error: (group.status?.size ?? 0) - (group.status?.running ?? 0)
134 subSystemCount: Array.isArray(subs) ? subs.length : 0,
135 gateWayNode: group.placement?.hosts?.length ?? 0,
136 created: group.status?.created ? new Date(group.status.created) : null
142 catchError((error) => {
143 this.context?.error?.(error);
152 this.subject.next([]);
155 updateSelection(selection: CdTableSelection): void {
156 this.selection = selection;
159 deleteGatewayGroupModal() {
160 const selectedGroup = this.selection.first();
161 if (!selectedGroup) {
165 service_name: serviceName,
169 const disableForm = selectedGroup.subSystemCount > 0 || !group;
171 this.modalService.show(DeleteConfirmationModalComponent, {
172 impact: DeletionImpact.high,
173 itemDescription: $localize`gateway group`,
174 bodyTemplate: this.deleteTpl,
175 itemNames: [selectedGroup.spec.group],
178 subsystemCount: selectedGroup.subSystemCount
180 submitActionObservable: () => {
181 return this.taskWrapper
182 .wrapTaskAroundCall({
183 task: new FinishedTask('nvmeof/gateway/delete', { group: selectedGroup.spec.group }),
184 call: this.cephServiceService.delete(serviceName)
188 this.table.refreshBtn();
190 catchError((error) => {
191 this.table.refreshBtn();
192 this.notificationService.show(
193 NotificationType.error,
194 $localize`${`Failed to delete gateway group ${selectedGroup.spec.group}: ${error.message}`}`