]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | import { Component, OnDestroy, OnInit } from '@angular/core'; |
2 | import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; | |
3 | ||
f67539c2 TL |
4 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; |
5 | import _ from 'lodash'; | |
9f95a23c TL |
6 | import { concat, forkJoin, Observable, Subscription } from 'rxjs'; |
7 | import { last } from 'rxjs/operators'; | |
8 | ||
f67539c2 TL |
9 | import { Pool } from '~/app/ceph/pool/pool'; |
10 | import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service'; | |
11 | import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; | |
12 | import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; | |
13 | import { FinishedTask } from '~/app/shared/models/finished-task'; | |
14 | import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service'; | |
9f95a23c TL |
15 | |
16 | @Component({ | |
17 | selector: 'cd-bootstrap-import-modal', | |
18 | templateUrl: './bootstrap-import-modal.component.html', | |
19 | styleUrls: ['./bootstrap-import-modal.component.scss'] | |
20 | }) | |
21 | export class BootstrapImportModalComponent implements OnInit, OnDestroy { | |
22 | siteName: string; | |
23 | pools: any[] = []; | |
24 | token: string; | |
25 | ||
26 | subs: Subscription; | |
27 | ||
28 | importBootstrapForm: CdFormGroup; | |
29 | ||
30 | directions: Array<any> = [ | |
31 | { key: 'rx-tx', desc: 'Bidirectional' }, | |
32 | { key: 'rx', desc: 'Unidirectional (receive-only)' } | |
33 | ]; | |
34 | ||
35 | constructor( | |
f67539c2 TL |
36 | public activeModal: NgbActiveModal, |
37 | public actionLabels: ActionLabelsI18n, | |
9f95a23c TL |
38 | private rbdMirroringService: RbdMirroringService, |
39 | private taskWrapper: TaskWrapperService | |
40 | ) { | |
41 | this.createForm(); | |
42 | } | |
43 | ||
44 | createForm() { | |
45 | this.importBootstrapForm = new CdFormGroup({ | |
46 | siteName: new FormControl('', { | |
47 | validators: [Validators.required] | |
48 | }), | |
49 | direction: new FormControl('rx-tx', {}), | |
50 | pools: new FormGroup( | |
51 | {}, | |
52 | { | |
53 | validators: [this.validatePools()] | |
54 | } | |
55 | ), | |
56 | token: new FormControl('', { | |
57 | validators: [Validators.required, this.validateToken()] | |
58 | }) | |
59 | }); | |
60 | } | |
61 | ||
62 | ngOnInit() { | |
63 | this.rbdMirroringService.getSiteName().subscribe((response: any) => { | |
64 | this.importBootstrapForm.get('siteName').setValue(response.site_name); | |
65 | }); | |
66 | ||
f6b5b4d7 | 67 | this.subs = this.rbdMirroringService.subscribeSummary((data) => { |
9f95a23c TL |
68 | const pools = data.content_data.pools; |
69 | this.pools = pools.reduce((acc: any[], pool: Pool) => { | |
70 | acc.push({ | |
71 | name: pool['name'], | |
72 | mirror_mode: pool['mirror_mode'] | |
73 | }); | |
74 | return acc; | |
75 | }, []); | |
76 | ||
77 | const poolsControl = this.importBootstrapForm.get('pools') as FormGroup; | |
78 | _.each(this.pools, (pool) => { | |
79 | const poolName = pool['name']; | |
80 | const mirroring_disabled = pool['mirror_mode'] === 'disabled'; | |
81 | const control = poolsControl.controls[poolName]; | |
82 | if (control) { | |
83 | if (mirroring_disabled && control.disabled) { | |
84 | control.enable(); | |
85 | } else if (!mirroring_disabled && control.enabled) { | |
86 | control.disable(); | |
87 | control.setValue(true); | |
88 | } | |
89 | } else { | |
90 | poolsControl.addControl( | |
91 | poolName, | |
92 | new FormControl({ value: !mirroring_disabled, disabled: !mirroring_disabled }) | |
93 | ); | |
94 | } | |
95 | }); | |
96 | }); | |
97 | } | |
98 | ||
99 | ngOnDestroy() { | |
100 | if (this.subs) { | |
101 | this.subs.unsubscribe(); | |
102 | } | |
103 | } | |
104 | ||
105 | validatePools(): ValidatorFn { | |
106 | return (poolsControl: FormGroup): { [key: string]: any } => { | |
107 | let checkedCount = 0; | |
108 | _.each(poolsControl.controls, (control) => { | |
109 | if (control.value === true) { | |
110 | ++checkedCount; | |
111 | } | |
112 | }); | |
113 | ||
114 | if (checkedCount > 0) { | |
115 | return null; | |
116 | } | |
117 | ||
118 | return { requirePool: true }; | |
119 | }; | |
120 | } | |
121 | ||
122 | validateToken(): ValidatorFn { | |
123 | return (token: FormControl): { [key: string]: any } => { | |
124 | try { | |
125 | if (JSON.parse(atob(token.value))) { | |
126 | return null; | |
127 | } | |
128 | } catch (error) {} | |
129 | return { invalidToken: true }; | |
130 | }; | |
131 | } | |
132 | ||
133 | import() { | |
134 | const bootstrapPoolNames: string[] = []; | |
135 | const poolNames: string[] = []; | |
136 | const poolsControl = this.importBootstrapForm.get('pools') as FormGroup; | |
137 | _.each(poolsControl.controls, (control, poolName) => { | |
138 | if (control.value === true) { | |
139 | bootstrapPoolNames.push(poolName); | |
140 | if (!control.disabled) { | |
141 | poolNames.push(poolName); | |
142 | } | |
143 | } | |
144 | }); | |
145 | ||
146 | const poolModeRequest = { | |
147 | mirror_mode: 'image' | |
148 | }; | |
149 | ||
150 | let apiActionsObs: Observable<any> = concat( | |
151 | this.rbdMirroringService.setSiteName(this.importBootstrapForm.getValue('siteName')), | |
152 | forkJoin( | |
153 | poolNames.map((poolName) => this.rbdMirroringService.updatePool(poolName, poolModeRequest)) | |
154 | ) | |
155 | ); | |
156 | ||
157 | apiActionsObs = bootstrapPoolNames | |
158 | .reduce((obs, poolName) => { | |
159 | return concat( | |
160 | obs, | |
161 | this.rbdMirroringService.importBootstrapToken( | |
162 | poolName, | |
163 | this.importBootstrapForm.getValue('direction'), | |
164 | this.importBootstrapForm.getValue('token') | |
165 | ) | |
166 | ); | |
167 | }, apiActionsObs) | |
168 | .pipe(last()); | |
169 | ||
170 | const finishHandler = () => { | |
171 | this.rbdMirroringService.refresh(); | |
172 | this.importBootstrapForm.setErrors({ cdSubmitButton: true }); | |
173 | }; | |
174 | ||
175 | const taskObs = this.taskWrapper.wrapTaskAroundCall({ | |
176 | task: new FinishedTask('rbd/mirroring/bootstrap/import', {}), | |
177 | call: apiActionsObs | |
178 | }); | |
f67539c2 TL |
179 | taskObs.subscribe({ |
180 | error: finishHandler, | |
181 | complete: () => { | |
182 | finishHandler(); | |
183 | this.activeModal.close(); | |
184 | } | |
9f95a23c TL |
185 | }); |
186 | } | |
187 | } |