]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/blob
cd6daf8ae2c6df25c79cfa3f13075ff59dddfa95
[ceph.git] /
1 import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
2
3 import { I18n } from '@ngx-translate/i18n-polyfill';
4 import * as _ from 'lodash';
5 import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
6 import { Subscription } from 'rxjs';
7
8 import { IscsiService } from '../../../shared/api/iscsi.service';
9 import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
10 import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
11 import { TableComponent } from '../../../shared/datatable/table/table.component';
12 import { CellTemplate } from '../../../shared/enum/cell-template.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 { FinishedTask } from '../../../shared/models/finished-task';
17 import { Permissions } from '../../../shared/models/permissions';
18 import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
19 import { AuthStorageService } from '../../../shared/services/auth-storage.service';
20 import { SummaryService } from '../../../shared/services/summary.service';
21 import { TaskListService } from '../../../shared/services/task-list.service';
22 import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
23 import { IscsiTargetDiscoveryModalComponent } from '../iscsi-target-discovery-modal/iscsi-target-discovery-modal.component';
24
25 @Component({
26   selector: 'cd-iscsi-target-list',
27   templateUrl: './iscsi-target-list.component.html',
28   styleUrls: ['./iscsi-target-list.component.scss'],
29   providers: [TaskListService]
30 })
31 export class IscsiTargetListComponent implements OnInit, OnDestroy {
32   @ViewChild(TableComponent)
33   table: TableComponent;
34
35   available: boolean = undefined;
36   columns: CdTableColumn[];
37   docsUrl: string;
38   modalRef: BsModalRef;
39   permissions: Permissions;
40   selection = new CdTableSelection();
41   cephIscsiConfigVersion: number;
42   settings: any;
43   status: string;
44   summaryDataSubscription: Subscription;
45   tableActions: CdTableAction[];
46   targets = [];
47
48   builders = {
49     'iscsi/target/create': (metadata) => {
50       return {
51         target_iqn: metadata['target_iqn']
52       };
53     }
54   };
55
56   constructor(
57     private authStorageService: AuthStorageService,
58     private i18n: I18n,
59     private iscsiService: IscsiService,
60     private taskListService: TaskListService,
61     private cephReleaseNamePipe: CephReleaseNamePipe,
62     private summaryservice: SummaryService,
63     private modalService: BsModalService,
64     private taskWrapper: TaskWrapperService,
65     public actionLabels: ActionLabelsI18n
66   ) {
67     this.permissions = this.authStorageService.getPermissions();
68
69     this.tableActions = [
70       {
71         permission: 'create',
72         icon: 'fa-plus',
73         routerLink: () => '/block/iscsi/targets/create',
74         name: this.actionLabels.CREATE
75       },
76       {
77         permission: 'update',
78         icon: 'fa-pencil',
79         routerLink: () => `/block/iscsi/targets/edit/${this.selection.first().target_iqn}`,
80         name: this.actionLabels.EDIT
81       },
82       {
83         permission: 'delete',
84         icon: 'fa-times',
85         click: () => this.deleteIscsiTargetModal(),
86         name: this.actionLabels.DELETE,
87         disable: () => !this.selection.first() || !_.isUndefined(this.getDeleteDisableDesc()),
88         disableDesc: () => this.getDeleteDisableDesc()
89       }
90     ];
91   }
92
93   ngOnInit() {
94     this.columns = [
95       {
96         name: this.i18n('Target'),
97         prop: 'target_iqn',
98         flexGrow: 2,
99         cellTransformation: CellTemplate.executing
100       },
101       {
102         name: this.i18n('Portals'),
103         prop: 'cdPortals',
104         flexGrow: 2
105       },
106       {
107         name: this.i18n('Images'),
108         prop: 'cdImages',
109         flexGrow: 2
110       },
111       {
112         name: this.i18n('# Sessions'),
113         prop: 'info.num_sessions',
114         flexGrow: 1
115       }
116     ];
117
118     this.iscsiService.status().subscribe((result: any) => {
119       this.available = result.available;
120
121       if (result.available) {
122         this.iscsiService.version().subscribe((res: any) => {
123           this.cephIscsiConfigVersion = res['ceph_iscsi_config_version'];
124           this.taskListService.init(
125             () => this.iscsiService.listTargets(),
126             (resp) => this.prepareResponse(resp),
127             (targets) => (this.targets = targets),
128             () => this.onFetchError(),
129             this.taskFilter,
130             this.itemFilter,
131             this.builders
132           );
133         });
134
135         this.iscsiService.settings().subscribe((settings: any) => {
136           this.settings = settings;
137         });
138       } else {
139         const summary = this.summaryservice.getCurrentSummary();
140         const releaseName = this.cephReleaseNamePipe.transform(summary.version);
141         this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/#enabling-iscsi-management`;
142         this.status = result.message;
143       }
144     });
145   }
146
147   ngOnDestroy() {
148     if (this.summaryDataSubscription) {
149       this.summaryDataSubscription.unsubscribe();
150     }
151   }
152
153   getDeleteDisableDesc(): string | undefined {
154     const first = this.selection.first();
155     if (first && first['info'] && first['info']['num_sessions']) {
156       return this.i18n('Target has active sessions');
157     }
158   }
159
160   prepareResponse(resp: any): any[] {
161     resp.forEach((element) => {
162       element.cdPortals = element.portals.map((portal) => `${portal.host}:${portal.ip}`);
163       element.cdImages = element.disks.map((disk) => `${disk.pool}/${disk.image}`);
164     });
165
166     return resp;
167   }
168
169   onFetchError() {
170     this.table.reset(); // Disable loading indicator.
171   }
172
173   itemFilter(entry, task) {
174     return entry.target_iqn === task.metadata['target_iqn'];
175   }
176
177   taskFilter(task) {
178     return ['iscsi/target/create', 'iscsi/target/edit', 'iscsi/target/delete'].includes(task.name);
179   }
180
181   updateSelection(selection: CdTableSelection) {
182     this.selection = selection;
183   }
184
185   deleteIscsiTargetModal() {
186     const target_iqn = this.selection.first().target_iqn;
187
188     this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
189       initialState: {
190         itemDescription: this.i18n('iSCSI target'),
191         itemNames: [target_iqn],
192         submitActionObservable: () =>
193           this.taskWrapper.wrapTaskAroundCall({
194             task: new FinishedTask('iscsi/target/delete', {
195               target_iqn: target_iqn
196             }),
197             call: this.iscsiService.deleteTarget(target_iqn)
198           })
199       }
200     });
201   }
202
203   configureDiscoveryAuth() {
204     this.modalService.show(IscsiTargetDiscoveryModalComponent, {});
205   }
206 }