1 import { Component, OnDestroy, OnInit, 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';
6 import { Subscription } from 'rxjs';
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';
26 selector: 'cd-iscsi-target-list',
27 templateUrl: './iscsi-target-list.component.html',
28 styleUrls: ['./iscsi-target-list.component.scss'],
29 providers: [TaskListService]
31 export class IscsiTargetListComponent implements OnInit, OnDestroy {
32 @ViewChild(TableComponent)
33 table: TableComponent;
35 available: boolean = undefined;
36 columns: CdTableColumn[];
39 permissions: Permissions;
40 selection = new CdTableSelection();
41 cephIscsiConfigVersion: number;
44 summaryDataSubscription: Subscription;
45 tableActions: CdTableAction[];
49 'iscsi/target/create': (metadata) => {
51 target_iqn: metadata['target_iqn']
57 private authStorageService: AuthStorageService,
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
67 this.permissions = this.authStorageService.getPermissions();
73 routerLink: () => '/block/iscsi/targets/create',
74 name: this.actionLabels.CREATE
79 routerLink: () => `/block/iscsi/targets/edit/${this.selection.first().target_iqn}`,
80 name: this.actionLabels.EDIT
85 click: () => this.deleteIscsiTargetModal(),
86 name: this.actionLabels.DELETE,
87 disable: () => !this.selection.first() || !_.isUndefined(this.getDeleteDisableDesc()),
88 disableDesc: () => this.getDeleteDisableDesc()
96 name: this.i18n('Target'),
99 cellTransformation: CellTemplate.executing
102 name: this.i18n('Portals'),
107 name: this.i18n('Images'),
112 name: this.i18n('# Sessions'),
113 prop: 'info.num_sessions',
118 this.iscsiService.status().subscribe((result: any) => {
119 this.available = result.available;
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(),
135 this.iscsiService.settings().subscribe((settings: any) => {
136 this.settings = settings;
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;
148 if (this.summaryDataSubscription) {
149 this.summaryDataSubscription.unsubscribe();
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');
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}`);
170 this.table.reset(); // Disable loading indicator.
173 itemFilter(entry, task) {
174 return entry.target_iqn === task.metadata['target_iqn'];
178 return ['iscsi/target/create', 'iscsi/target/edit', 'iscsi/target/delete'].includes(task.name);
181 updateSelection(selection: CdTableSelection) {
182 this.selection = selection;
185 deleteIscsiTargetModal() {
186 const target_iqn = this.selection.first().target_iqn;
188 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
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
197 call: this.iscsiService.deleteTarget(target_iqn)
203 configureDiscoveryAuth() {
204 this.modalService.show(IscsiTargetDiscoveryModalComponent, {});