]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/blob
2e3ecbaec5514aa80b63e245b449eda1cc5afe8f
[ceph.git] /
1 import { Component, Input, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core';
2
3 import * as _ from 'lodash';
4 import { BsModalRef, BsModalService } from 'ngx-bootstrap';
5
6 import { RbdService } from '../../../shared/api/rbd.service';
7 import { DeletionModalComponent } from '../../../shared/components/deletion-modal/deletion-modal.component';
8 import { CellTemplate } from '../../../shared/enum/cell-template.enum';
9 import { CdTableColumn } from '../../../shared/models/cd-table-column';
10 import { CdTableSelection } from '../../../shared/models/cd-table-selection';
11 import { ExecutingTask } from '../../../shared/models/executing-task';
12 import { FinishedTask } from '../../../shared/models/finished-task';
13 import { CdDatePipe } from '../../../shared/pipes/cd-date.pipe';
14 import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
15 import { NotificationService } from '../../../shared/services/notification.service';
16 import { TaskManagerService } from '../../../shared/services/task-manager.service';
17 import { RbdSnapshotFormComponent } from '../rbd-snapshot-form/rbd-snapshot-form.component';
18 import { RollbackConfirmationModalComponent } from '../rollback-confirmation-modal/rollback-confimation-modal.component';
19 import { RbdSnapshotModel } from './rbd-snapshot.model';
20
21 @Component({
22   selector: 'cd-rbd-snapshot-list',
23   templateUrl: './rbd-snapshot-list.component.html',
24   styleUrls: ['./rbd-snapshot-list.component.scss']
25 })
26 export class RbdSnapshotListComponent implements OnInit, OnChanges {
27   @Input() snapshots: RbdSnapshotModel[] = [];
28   @Input() poolName: string;
29   @Input() rbdName: string;
30   @Input() executingTasks: ExecutingTask[] = [];
31
32   @ViewChild('nameTpl') nameTpl: TemplateRef<any>;
33   @ViewChild('protectTpl') protectTpl: TemplateRef<any>;
34
35   data: RbdSnapshotModel[];
36
37   columns: CdTableColumn[];
38
39   modalRef: BsModalRef;
40
41   selection = new CdTableSelection();
42
43   constructor(
44     private modalService: BsModalService,
45     private dimlessBinaryPipe: DimlessBinaryPipe,
46     private cdDatePipe: CdDatePipe,
47     private rbdService: RbdService,
48     private taskManagerService: TaskManagerService,
49     private notificationService: NotificationService
50   ) {}
51
52   ngOnInit() {
53     this.columns = [
54       {
55         name: 'Name',
56         prop: 'name',
57         cellTransformation: CellTemplate.executing,
58         flexGrow: 2
59       },
60       {
61         name: 'Size',
62         prop: 'size',
63         flexGrow: 1,
64         cellClass: 'text-right',
65         pipe: this.dimlessBinaryPipe
66       },
67       {
68         name: 'Provisioned',
69         prop: 'disk_usage',
70         flexGrow: 1,
71         cellClass: 'text-right',
72         pipe: this.dimlessBinaryPipe
73       },
74       {
75         name: 'State',
76         prop: 'is_protected',
77         flexGrow: 1,
78         cellClass: 'text-center',
79         cellTemplate: this.protectTpl
80       },
81       {
82         name: 'Created',
83         prop: 'timestamp',
84         flexGrow: 1,
85         pipe: this.cdDatePipe
86       }
87     ];
88   }
89
90   ngOnChanges() {
91     this.data = this.merge(this.snapshots, this.executingTasks);
92   }
93
94   private merge(snapshots: RbdSnapshotModel[], executingTasks: ExecutingTask[] = []) {
95     const resultSnapshots = _.clone(snapshots);
96     executingTasks.forEach((executingTask) => {
97       const snapshotExecuting = resultSnapshots.find((snapshot) => {
98         return snapshot.name === executingTask.metadata['snapshot_name'];
99       });
100       if (snapshotExecuting) {
101         if (executingTask.name === 'rbd/snap/delete') {
102           snapshotExecuting.cdExecuting = 'deleting';
103         } else if (executingTask.name === 'rbd/snap/edit') {
104           snapshotExecuting.cdExecuting = 'updating';
105         } else if (executingTask.name === 'rbd/snap/rollback') {
106           snapshotExecuting.cdExecuting = 'rolling back';
107         }
108       } else if (executingTask.name === 'rbd/snap/create') {
109         const rbdSnapshotModel = new RbdSnapshotModel();
110         rbdSnapshotModel.name = executingTask.metadata['snapshot_name'];
111         rbdSnapshotModel.cdExecuting = 'creating';
112         this.pushIfNotExists(resultSnapshots, rbdSnapshotModel);
113       }
114     });
115     return resultSnapshots;
116   }
117
118   private pushIfNotExists(resultSnapshots: RbdSnapshotModel[], rbdSnapshotModel: RbdSnapshotModel) {
119     const exists = resultSnapshots.some((resultSnapshot) => {
120       return resultSnapshot.name === rbdSnapshotModel.name;
121     });
122     if (!exists) {
123       resultSnapshots.push(rbdSnapshotModel);
124     }
125   }
126
127   private openSnapshotModal(taskName: string, oldSnapshotName: string = null) {
128     this.modalRef = this.modalService.show(RbdSnapshotFormComponent);
129     this.modalRef.content.poolName = this.poolName;
130     this.modalRef.content.imageName = this.rbdName;
131     if (oldSnapshotName) {
132       this.modalRef.content.setSnapName(this.selection.first().name);
133     }
134     this.modalRef.content.onSubmit.subscribe((snapshotName: string) => {
135       const executingTask = new ExecutingTask();
136       executingTask.name = taskName;
137       executingTask.metadata = { snapshot_name: snapshotName };
138       this.executingTasks.push(executingTask);
139       this.ngOnChanges();
140     });
141   }
142
143   openCreateSnapshotModal() {
144     this.openSnapshotModal('rbd/snap/create');
145   }
146
147   openEditSnapshotModal() {
148     this.openSnapshotModal('rbd/snap/edit', this.selection.first().name);
149   }
150
151   toggleProtection() {
152     const snapshotName = this.selection.first().name;
153     const isProtected = this.selection.first().is_protected;
154     const finishedTask = new FinishedTask();
155     finishedTask.name = 'rbd/snap/edit';
156     finishedTask.metadata = {
157       pool_name: this.poolName,
158       image_name: this.rbdName,
159       snapshot_name: snapshotName
160     };
161     this.rbdService
162       .protectSnapshot(this.poolName, this.rbdName, snapshotName, !isProtected)
163       .toPromise()
164       .then((resp) => {
165         const executingTask = new ExecutingTask();
166         executingTask.name = finishedTask.name;
167         executingTask.metadata = finishedTask.metadata;
168         this.executingTasks.push(executingTask);
169         this.ngOnChanges();
170         this.taskManagerService.subscribe(
171           finishedTask.name,
172           finishedTask.metadata,
173           (asyncFinishedTask: FinishedTask) => {
174             this.notificationService.notifyTask(asyncFinishedTask);
175           }
176         );
177       });
178   }
179
180   _asyncTask(task: string, taskName: string, snapshotName: string) {
181     const finishedTask = new FinishedTask();
182     finishedTask.name = taskName;
183     finishedTask.metadata = {
184       pool_name: this.poolName,
185       image_name: this.rbdName,
186       snapshot_name: snapshotName
187     };
188     this.rbdService[task](this.poolName, this.rbdName, snapshotName)
189       .toPromise()
190       .then(() => {
191         const executingTask = new ExecutingTask();
192         executingTask.name = finishedTask.name;
193         executingTask.metadata = finishedTask.metadata;
194         this.executingTasks.push(executingTask);
195         this.modalRef.hide();
196         this.ngOnChanges();
197         this.taskManagerService.subscribe(
198           executingTask.name,
199           executingTask.metadata,
200           (asyncFinishedTask: FinishedTask) => {
201             this.notificationService.notifyTask(asyncFinishedTask);
202           }
203         );
204       })
205       .catch((resp) => {
206         this.modalRef.content.stopLoadingSpinner();
207       });
208   }
209
210   rollbackModal() {
211     const snapshotName = this.selection.selected[0].name;
212     this.modalRef = this.modalService.show(RollbackConfirmationModalComponent);
213     this.modalRef.content.snapName = `${this.poolName}/${this.rbdName}@${snapshotName}`;
214     this.modalRef.content.onSubmit.subscribe((itemName: string) => {
215       this._asyncTask('rollbackSnapshot', 'rbd/snap/rollback', snapshotName);
216     });
217   }
218
219   deleteSnapshotModal() {
220     const snapshotName = this.selection.selected[0].name;
221     this.modalRef = this.modalService.show(DeletionModalComponent);
222     this.modalRef.content.setUp({
223       metaType: 'RBD snapshot',
224       pattern: snapshotName,
225       deletionMethod: () => this._asyncTask('deleteSnapshot', 'rbd/snap/delete', snapshotName),
226       modalRef: this.modalRef
227     });
228   }
229
230   updateSelection(selection: CdTableSelection) {
231     this.selection = selection;
232   }
233 }