]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-trash-list/rbd-trash-list.component.ts
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / block / rbd-trash-list / rbd-trash-list.component.ts
CommitLineData
11fdf7f2
TL
1import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
2
f67539c2
TL
3import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
4import _ from 'lodash';
5import moment from 'moment';
6
7import { RbdService } from '~/app/shared/api/rbd.service';
8import { TableStatusViewCache } from '~/app/shared/classes/table-status-view-cache';
9import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
10import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
11import { TableComponent } from '~/app/shared/datatable/table/table.component';
12import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
13import { Icons } from '~/app/shared/enum/icons.enum';
14import { ViewCacheStatus } from '~/app/shared/enum/view-cache-status.enum';
15import { CdTableAction } from '~/app/shared/models/cd-table-action';
16import { CdTableColumn } from '~/app/shared/models/cd-table-column';
17import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
18import { ExecutingTask } from '~/app/shared/models/executing-task';
19import { FinishedTask } from '~/app/shared/models/finished-task';
20import { ImageSpec } from '~/app/shared/models/image-spec';
21import { Permission } from '~/app/shared/models/permissions';
22import { Task } from '~/app/shared/models/task';
23import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
24import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
25import { ModalService } from '~/app/shared/services/modal.service';
26import { TaskListService } from '~/app/shared/services/task-list.service';
27import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
11fdf7f2
TL
28import { RbdTrashPurgeModalComponent } from '../rbd-trash-purge-modal/rbd-trash-purge-modal.component';
29import { RbdTrashRestoreModalComponent } from '../rbd-trash-restore-modal/rbd-trash-restore-modal.component';
30
31@Component({
32 selector: 'cd-rbd-trash-list',
33 templateUrl: './rbd-trash-list.component.html',
34 styleUrls: ['./rbd-trash-list.component.scss'],
35 providers: [TaskListService]
36})
37export class RbdTrashListComponent implements OnInit {
9f95a23c 38 @ViewChild(TableComponent, { static: true })
11fdf7f2 39 table: TableComponent;
9f95a23c 40 @ViewChild('expiresTpl', { static: true })
11fdf7f2 41 expiresTpl: TemplateRef<any>;
9f95a23c 42 @ViewChild('deleteTpl', { static: true })
11fdf7f2
TL
43 deleteTpl: TemplateRef<any>;
44
9f95a23c
TL
45 icons = Icons;
46
11fdf7f2
TL
47 columns: CdTableColumn[];
48 executingTasks: ExecutingTask[] = [];
49 images: any;
f67539c2 50 modalRef: NgbModalRef;
11fdf7f2
TL
51 permission: Permission;
52 retries: number;
53 selection = new CdTableSelection();
54 tableActions: CdTableAction[];
f67539c2 55 tableStatus = new TableStatusViewCache();
9f95a23c 56 disablePurgeBtn = true;
11fdf7f2
TL
57
58 constructor(
59 private authStorageService: AuthStorageService,
60 private rbdService: RbdService,
f67539c2 61 private modalService: ModalService,
11fdf7f2 62 private cdDatePipe: CdDatePipe,
f67539c2 63 public taskListService: TaskListService,
11fdf7f2 64 private taskWrapper: TaskWrapperService,
eafe8130 65 public actionLabels: ActionLabelsI18n
11fdf7f2
TL
66 ) {
67 this.permission = this.authStorageService.getPermissions().rbdImage;
11fdf7f2
TL
68 const restoreAction: CdTableAction = {
69 permission: 'update',
9f95a23c 70 icon: Icons.undo,
11fdf7f2 71 click: () => this.restoreModal(),
eafe8130 72 name: this.actionLabels.RESTORE
11fdf7f2
TL
73 };
74 const deleteAction: CdTableAction = {
75 permission: 'delete',
9f95a23c 76 icon: Icons.destroy,
11fdf7f2 77 click: () => this.deleteModal(),
eafe8130 78 name: this.actionLabels.DELETE
11fdf7f2
TL
79 };
80 this.tableActions = [restoreAction, deleteAction];
81 }
82
83 ngOnInit() {
84 this.columns = [
85 {
f67539c2 86 name: $localize`ID`,
11fdf7f2
TL
87 prop: 'id',
88 flexGrow: 1,
89 cellTransformation: CellTemplate.executing
90 },
91 {
f67539c2 92 name: $localize`Name`,
11fdf7f2
TL
93 prop: 'name',
94 flexGrow: 1
95 },
96 {
f67539c2 97 name: $localize`Pool`,
11fdf7f2
TL
98 prop: 'pool_name',
99 flexGrow: 1
100 },
9f95a23c 101 {
f67539c2 102 name: $localize`Namespace`,
9f95a23c
TL
103 prop: 'namespace',
104 flexGrow: 1
105 },
11fdf7f2 106 {
f67539c2 107 name: $localize`Status`,
11fdf7f2
TL
108 prop: 'deferment_end_time',
109 flexGrow: 1,
110 cellTemplate: this.expiresTpl
111 },
112 {
f67539c2 113 name: $localize`Deleted At`,
11fdf7f2
TL
114 prop: 'deletion_time',
115 flexGrow: 1,
116 pipe: this.cdDatePipe
117 }
118 ];
119
9f95a23c
TL
120 const itemFilter = (entry: any, task: Task) => {
121 const imageSpec = new ImageSpec(entry.pool_name, entry.namespace, entry.id);
122 return imageSpec.toString() === task.metadata['image_id_spec'];
123 };
124
125 const taskFilter = (task: Task) => {
126 return ['rbd/trash/remove', 'rbd/trash/restore'].includes(task.name);
127 };
128
11fdf7f2
TL
129 this.taskListService.init(
130 () => this.rbdService.listTrash(),
131 (resp) => this.prepareResponse(resp),
132 (images) => (this.images = images),
133 () => this.onFetchError(),
9f95a23c
TL
134 taskFilter,
135 itemFilter,
11fdf7f2
TL
136 undefined
137 );
138 }
139
140 prepareResponse(resp: any[]): any[] {
9f95a23c 141 let images: any[] = [];
11fdf7f2 142 const viewCacheStatusMap = {};
f67539c2 143
9f95a23c 144 resp.forEach((pool: Record<string, any>) => {
11fdf7f2
TL
145 if (_.isUndefined(viewCacheStatusMap[pool.status])) {
146 viewCacheStatusMap[pool.status] = [];
147 }
148 viewCacheStatusMap[pool.status].push(pool.pool_name);
149 images = images.concat(pool.value);
9f95a23c 150 this.disablePurgeBtn = !images.length;
11fdf7f2
TL
151 });
152
f67539c2
TL
153 let status: number;
154 if (viewCacheStatusMap[3]) {
155 status = 3;
156 } else if (viewCacheStatusMap[1]) {
157 status = 1;
158 } else if (viewCacheStatusMap[2]) {
159 status = 2;
160 }
161
162 if (status) {
163 const statusFor =
164 (viewCacheStatusMap[status].length > 1 ? 'pools ' : 'pool ') +
165 viewCacheStatusMap[status].join();
166
167 this.tableStatus = new TableStatusViewCache(status, statusFor);
168 } else {
169 this.tableStatus = new TableStatusViewCache();
170 }
171
11fdf7f2
TL
172 images.forEach((image) => {
173 image.cdIsExpired = moment().isAfter(image.deferment_end_time);
174 });
f67539c2 175
11fdf7f2
TL
176 return images;
177 }
178
179 onFetchError() {
180 this.table.reset(); // Disable loading indicator.
f67539c2 181 this.tableStatus = new TableStatusViewCache(ViewCacheStatus.ValueException);
11fdf7f2
TL
182 }
183
11fdf7f2
TL
184 updateSelection(selection: CdTableSelection) {
185 this.selection = selection;
186 }
187
188 restoreModal() {
189 const initialState = {
11fdf7f2 190 poolName: this.selection.first().pool_name,
9f95a23c 191 namespace: this.selection.first().namespace,
11fdf7f2
TL
192 imageName: this.selection.first().name,
193 imageId: this.selection.first().id
194 };
195
f67539c2 196 this.modalRef = this.modalService.show(RbdTrashRestoreModalComponent, initialState);
11fdf7f2
TL
197 }
198
199 deleteModal() {
200 const poolName = this.selection.first().pool_name;
9f95a23c 201 const namespace = this.selection.first().namespace;
11fdf7f2
TL
202 const imageId = this.selection.first().id;
203 const expiresAt = this.selection.first().deferment_end_time;
f67539c2 204 const isExpired = moment().isAfter(expiresAt);
9f95a23c 205 const imageIdSpec = new ImageSpec(poolName, namespace, imageId);
11fdf7f2
TL
206
207 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
f67539c2
TL
208 itemDescription: 'RBD',
209 itemNames: [imageIdSpec],
210 bodyTemplate: this.deleteTpl,
211 bodyContext: { expiresAt, isExpired },
212 submitActionObservable: () =>
213 this.taskWrapper.wrapTaskAroundCall({
214 task: new FinishedTask('rbd/trash/remove', {
215 image_id_spec: imageIdSpec.toString()
216 }),
217 call: this.rbdService.removeTrash(imageIdSpec, true)
218 })
11fdf7f2
TL
219 });
220 }
221
11fdf7f2
TL
222 purgeModal() {
223 this.modalService.show(RbdTrashPurgeModalComponent);
224 }
225}