]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-list/nfs-list.component.ts
d/control: depend on python3-yaml for ceph-mgr
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / nfs / nfs-list / nfs-list.component.ts
CommitLineData
11fdf7f2
TL
1import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
2
3import { I18n } from '@ngx-translate/i18n-polyfill';
4import * as _ from 'lodash';
5import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
6import { Subscription } from 'rxjs';
7
8import { NfsService } from '../../../shared/api/nfs.service';
9import { CriticalConfirmationModalComponent } from '../../../shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
eafe8130 10import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
11fdf7f2
TL
11import { TableComponent } from '../../../shared/datatable/table/table.component';
12import { CellTemplate } from '../../../shared/enum/cell-template.enum';
9f95a23c 13import { Icons } from '../../../shared/enum/icons.enum';
11fdf7f2
TL
14import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
15import { CdTableAction } from '../../../shared/models/cd-table-action';
16import { CdTableColumn } from '../../../shared/models/cd-table-column';
17import { CdTableSelection } from '../../../shared/models/cd-table-selection';
18import { FinishedTask } from '../../../shared/models/finished-task';
19import { Permission } from '../../../shared/models/permissions';
9f95a23c 20import { Task } from '../../../shared/models/task';
11fdf7f2
TL
21import { AuthStorageService } from '../../../shared/services/auth-storage.service';
22import { TaskListService } from '../../../shared/services/task-list.service';
23import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
24
25@Component({
26 selector: 'cd-nfs-list',
27 templateUrl: './nfs-list.component.html',
28 styleUrls: ['./nfs-list.component.scss'],
29 providers: [TaskListService]
30})
31export class NfsListComponent implements OnInit, OnDestroy {
9f95a23c 32 @ViewChild('nfsState', { static: false })
11fdf7f2 33 nfsState: TemplateRef<any>;
9f95a23c 34 @ViewChild('nfsFsal', { static: true })
11fdf7f2
TL
35 nfsFsal: TemplateRef<any>;
36
9f95a23c 37 @ViewChild('table', { static: true })
11fdf7f2
TL
38 table: TableComponent;
39
40 columns: CdTableColumn[];
41 permission: Permission;
42 selection = new CdTableSelection();
43 summaryDataSubscription: Subscription;
44 viewCacheStatus: any;
45 exports: any[];
46 tableActions: CdTableAction[];
47 isDefaultCluster = false;
48
49 modalRef: BsModalRef;
50
51 builders = {
9f95a23c 52 'nfs/create': (metadata: any) => {
11fdf7f2
TL
53 return {
54 path: metadata['path'],
55 cluster_id: metadata['cluster_id'],
56 fsal: metadata['fsal']
57 };
58 }
59 };
60
61 constructor(
62 private authStorageService: AuthStorageService,
63 private i18n: I18n,
64 private modalService: BsModalService,
65 private nfsService: NfsService,
66 private taskListService: TaskListService,
eafe8130
TL
67 private taskWrapper: TaskWrapperService,
68 public actionLabels: ActionLabelsI18n
11fdf7f2
TL
69 ) {
70 this.permission = this.authStorageService.getPermissions().nfs;
71 const getNfsUri = () =>
72 this.selection.first() &&
73 `${encodeURI(this.selection.first().cluster_id)}/${encodeURI(
74 this.selection.first().export_id
75 )}`;
76
eafe8130 77 const createAction: CdTableAction = {
11fdf7f2 78 permission: 'create',
9f95a23c 79 icon: Icons.add,
eafe8130 80 routerLink: () => '/nfs/create',
11fdf7f2 81 canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
eafe8130 82 name: this.actionLabels.CREATE
11fdf7f2
TL
83 };
84
85 const editAction: CdTableAction = {
86 permission: 'update',
9f95a23c 87 icon: Icons.edit,
11fdf7f2 88 routerLink: () => `/nfs/edit/${getNfsUri()}`,
eafe8130 89 name: this.actionLabels.EDIT
11fdf7f2
TL
90 };
91
92 const deleteAction: CdTableAction = {
93 permission: 'delete',
9f95a23c 94 icon: Icons.destroy,
11fdf7f2 95 click: () => this.deleteNfsModal(),
eafe8130 96 name: this.actionLabels.DELETE
11fdf7f2
TL
97 };
98
eafe8130 99 this.tableActions = [createAction, editAction, deleteAction];
11fdf7f2
TL
100 }
101
102 ngOnInit() {
103 this.columns = [
104 {
eafe8130 105 name: this.i18n('Path'),
11fdf7f2
TL
106 prop: 'path',
107 flexGrow: 2,
108 cellTransformation: CellTemplate.executing
109 },
eafe8130
TL
110 {
111 name: this.i18n('Pseudo'),
112 prop: 'pseudo',
113 flexGrow: 2
114 },
11fdf7f2
TL
115 {
116 name: this.i18n('Cluster'),
117 prop: 'cluster_id',
118 flexGrow: 2
119 },
120 {
121 name: this.i18n('Daemons'),
122 prop: 'daemons',
123 flexGrow: 2
124 },
125 {
126 name: this.i18n('Storage Backend'),
127 prop: 'fsal',
128 flexGrow: 2,
129 cellTemplate: this.nfsFsal
130 },
131 {
132 name: this.i18n('Access Type'),
133 prop: 'access_type',
134 flexGrow: 2
135 }
136 ];
137
138 this.nfsService.daemon().subscribe(
139 (daemons: any) => {
140 const clusters = _(daemons)
141 .map((daemon) => daemon.cluster_id)
142 .uniq()
143 .value();
144
145 this.isDefaultCluster = clusters.length === 1 && clusters[0] === '_default_';
eafe8130 146 this.columns[2].isHidden = this.isDefaultCluster;
11fdf7f2
TL
147 if (this.table) {
148 this.table.updateColumns();
149 }
150
151 this.taskListService.init(
152 () => this.nfsService.list(),
153 (resp) => this.prepareResponse(resp),
154 (exports) => (this.exports = exports),
155 () => this.onFetchError(),
156 this.taskFilter,
157 this.itemFilter,
158 this.builders
159 );
160 },
161 () => {
162 this.onFetchError();
163 }
164 );
165 }
166
167 ngOnDestroy() {
168 if (this.summaryDataSubscription) {
169 this.summaryDataSubscription.unsubscribe();
170 }
171 }
172
173 prepareResponse(resp: any): any[] {
9f95a23c
TL
174 let result: any[] = [];
175 resp.forEach((nfs: any) => {
11fdf7f2
TL
176 nfs.id = `${nfs.cluster_id}:${nfs.export_id}`;
177 nfs.state = 'LOADING';
178 result = result.concat(nfs);
179 });
180
181 return result;
182 }
183
184 onFetchError() {
185 this.table.reset(); // Disable loading indicator.
186 this.viewCacheStatus = { status: ViewCacheStatus.ValueException };
187 }
188
9f95a23c 189 itemFilter(entry: any, task: Task) {
11fdf7f2
TL
190 return (
191 entry.cluster_id === task.metadata['cluster_id'] &&
192 entry.export_id === task.metadata['export_id']
193 );
194 }
195
9f95a23c 196 taskFilter(task: Task) {
11fdf7f2
TL
197 return ['nfs/create', 'nfs/delete', 'nfs/edit'].includes(task.name);
198 }
199
200 updateSelection(selection: CdTableSelection) {
201 this.selection = selection;
202 }
203
204 deleteNfsModal() {
205 const cluster_id = this.selection.first().cluster_id;
206 const export_id = this.selection.first().export_id;
207
208 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
209 initialState: {
eafe8130
TL
210 itemDescription: this.i18n('NFS export'),
211 itemNames: [`${cluster_id}:${export_id}`],
11fdf7f2
TL
212 submitActionObservable: () =>
213 this.taskWrapper.wrapTaskAroundCall({
214 task: new FinishedTask('nfs/delete', {
215 cluster_id: cluster_id,
216 export_id: export_id
217 }),
218 call: this.nfsService.delete(cluster_id, export_id)
219 })
220 }
221 });
222 }
223}