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