]> git.apps.os.sepia.ceph.com Git - ceph.git/blob
f84419dd7a8380585421136056d3f2e774574b39
[ceph.git] /
1 import { Component, OnInit } from '@angular/core';
2 import { UntypedFormControl, Validators } from '@angular/forms';
3 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 import { Subscription, forkJoin } from 'rxjs';
5 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
6 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
7 import { WizardStepModel } from '~/app/shared/models/wizard-steps';
8 import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
9 import { RgwDaemonService } from '~/app/shared/api/rgw-daemon.service';
10 import { RgwDaemon } from '../models/rgw-daemon';
11 import { MultiClusterService } from '~/app/shared/api/multi-cluster.service';
12 import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
13 import { Icons } from '~/app/shared/enum/icons.enum';
14 import { SelectOption } from '~/app/shared/components/select/select-option.model';
15 import _ from 'lodash';
16 import { SelectMessages } from '~/app/shared/components/select/select-messages.model';
17 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
18 import { NotificationService } from '~/app/shared/services/notification.service';
19 import { Router } from '@angular/router';
20 import { map, switchMap } from 'rxjs/operators';
21
22 @Component({
23   selector: 'cd-rgw-multisite-wizard',
24   templateUrl: './rgw-multisite-wizard.component.html',
25   styleUrls: ['./rgw-multisite-wizard.component.scss']
26 })
27 export class RgwMultisiteWizardComponent implements OnInit {
28   multisiteSetupForm: CdFormGroup;
29   currentStep: WizardStepModel;
30   currentStepSub: Subscription;
31   permissions: Permissions;
32   stepTitles = ['Create Realm & Zonegroup', 'Create Zone', 'Select Cluster'];
33   stepsToSkip: { [steps: string]: boolean } = {};
34   daemons: RgwDaemon[] = [];
35   selectedCluster = '';
36   clusterDetailsArray: any;
37   isMultiClusterConfigured = false;
38   exportTokenForm: CdFormGroup;
39   realms: any;
40   loading = false;
41   pageURL: string;
42   icons = Icons;
43   rgwEndpoints: { value: any[]; options: any[]; messages: any };
44
45   constructor(
46     private wizardStepsService: WizardStepsService,
47     public activeModal: NgbActiveModal,
48     public actionLabels: ActionLabelsI18n,
49     private rgwDaemonService: RgwDaemonService,
50     private multiClusterService: MultiClusterService,
51     private rgwMultisiteService: RgwMultisiteService,
52     public notificationService: NotificationService,
53     private router: Router
54   ) {
55     this.pageURL = 'rgw/multisite';
56     this.currentStepSub = this.wizardStepsService
57       .getCurrentStep()
58       .subscribe((step: WizardStepModel) => {
59         this.currentStep = step;
60       });
61     this.currentStep.stepIndex = 1;
62     this.createForm();
63     this.rgwEndpoints = {
64       value: [],
65       options: [],
66       messages: new SelectMessages({
67         empty: $localize`There are no endpoints.`,
68         filter: $localize`Select endpoints`
69       })
70     };
71   }
72
73   ngOnInit(): void {
74     this.rgwDaemonService
75       .list()
76       .pipe(
77         switchMap((daemons) => {
78           this.daemons = daemons;
79           const daemonStatsObservables = daemons.map((daemon) =>
80             this.rgwDaemonService.get(daemon.id).pipe(
81               map((daemonStats) => ({
82                 hostname: daemon.server_hostname,
83                 port: daemon.port,
84                 frontendConfig: daemonStats['rgw_metadata']['frontend_config#0']
85               }))
86             )
87           );
88           return forkJoin(daemonStatsObservables);
89         })
90       )
91       .subscribe((daemonStatsArray) => {
92         this.rgwEndpoints.value = daemonStatsArray.map((daemonStats) => {
93           const protocol = daemonStats.frontendConfig.includes('ssl_port') ? 'https' : 'http';
94           return `${protocol}://${daemonStats.hostname}:${daemonStats.port}`;
95         });
96         const options: SelectOption[] = this.rgwEndpoints.value.map(
97           (endpoint: string) => new SelectOption(false, endpoint, '')
98         );
99         this.rgwEndpoints.options = [...options];
100       });
101
102     this.multiClusterService.getCluster().subscribe((clusters) => {
103       this.clusterDetailsArray = Object.values(clusters['config'])
104         .flat()
105         .filter((cluster) => cluster['cluster_alias'] !== 'local-cluster');
106       this.isMultiClusterConfigured = this.clusterDetailsArray.length > 0;
107       if (!this.isMultiClusterConfigured) {
108         this.stepTitles = ['Create Realm & Zonegroup', 'Create Zone', 'Export Multi-site token'];
109       } else {
110         this.selectedCluster = this.clusterDetailsArray[0]['name'];
111       }
112     });
113   }
114
115   createForm() {
116     this.multisiteSetupForm = new CdFormGroup({
117       realmName: new UntypedFormControl('default_realm', {
118         validators: [Validators.required]
119       }),
120       zonegroupName: new UntypedFormControl('default_zonegroup', {
121         validators: [Validators.required]
122       }),
123       zonegroup_endpoints: new UntypedFormControl(null, [Validators.required]),
124       zoneName: new UntypedFormControl('default_zone', {
125         validators: [Validators.required]
126       }),
127       zone_endpoints: new UntypedFormControl(null, {
128         validators: [Validators.required]
129       }),
130       username: new UntypedFormControl('default_system_user', {
131         validators: [Validators.required]
132       }),
133       cluster: new UntypedFormControl(null, {
134         validators: [Validators.required]
135       })
136     });
137
138     if (!this.isMultiClusterConfigured) {
139       this.exportTokenForm = new CdFormGroup({});
140     }
141   }
142
143   showSubmitButtonLabel() {
144     if (this.isMultiClusterConfigured) {
145       return !this.wizardStepsService.isLastStep()
146         ? this.actionLabels.NEXT
147         : $localize`Configure Multi-site`;
148     } else {
149       return !this.wizardStepsService.isLastStep() ? this.actionLabels.NEXT : $localize`Close`;
150     }
151   }
152
153   showCancelButtonLabel() {
154     return !this.wizardStepsService.isFirstStep()
155       ? this.actionLabels.BACK
156       : this.actionLabels.CANCEL;
157   }
158
159   onNextStep() {
160     if (!this.wizardStepsService.isLastStep()) {
161       this.wizardStepsService.getCurrentStep().subscribe((step: WizardStepModel) => {
162         this.currentStep = step;
163       });
164       if (this.currentStep.stepIndex === 2 && !this.isMultiClusterConfigured) {
165         this.onSubmit();
166       } else {
167         this.wizardStepsService.moveToNextStep();
168       }
169     } else {
170       this.onSubmit();
171     }
172   }
173
174   onSubmit() {
175     this.loading = true;
176     const values = this.multisiteSetupForm.value;
177     const realmName = values['realmName'];
178     const zonegroupName = values['zonegroupName'];
179     const zonegroupEndpoints = this.rgwEndpoints.value.join(',');
180     const zoneName = values['zoneName'];
181     const zoneEndpoints = this.rgwEndpoints.value.join(',');
182     const username = values['username'];
183     if (!this.isMultiClusterConfigured) {
184       if (this.wizardStepsService.isLastStep()) {
185         this.activeModal.close();
186         this.refreshMultisitePage();
187       } else {
188         this.rgwMultisiteService
189           .setUpMultisiteReplication(
190             realmName,
191             zonegroupName,
192             zonegroupEndpoints,
193             zoneName,
194             zoneEndpoints,
195             username
196           )
197           .subscribe((data: object[]) => {
198             this.loading = false;
199             this.realms = data;
200             this.wizardStepsService.moveToNextStep();
201             this.showSuccessNotification();
202           });
203       }
204     } else {
205       const cluster = values['cluster'];
206       this.rgwMultisiteService
207         .setUpMultisiteReplication(
208           realmName,
209           zonegroupName,
210           zonegroupEndpoints,
211           zoneName,
212           zoneEndpoints,
213           username,
214           cluster
215         )
216         .subscribe(
217           () => {
218             this.showSuccessNotification();
219             this.activeModal.close();
220             this.refreshMultisitePage();
221           },
222           () => {
223             this.multisiteSetupForm.setErrors({ cdSubmitButton: true });
224           }
225         );
226     }
227   }
228
229   showSuccessNotification() {
230     this.notificationService.show(
231       NotificationType.success,
232       $localize`Multi-site setup completed successfully.`
233     );
234   }
235
236   refreshMultisitePage() {
237     const currentRoute = this.router.url.split('?')[0];
238     const navigateTo = currentRoute.includes('multisite') ? '/pool' : '/';
239     this.router.navigateByUrl(navigateTo, { skipLocationChange: true }).then(() => {
240       this.router.navigate([currentRoute]);
241     });
242   }
243
244   onPreviousStep() {
245     if (!this.wizardStepsService.isFirstStep()) {
246       this.wizardStepsService.moveToPreviousStep();
247     } else {
248       this.activeModal.close();
249     }
250   }
251
252   onSkip() {
253     const stepTitle = this.stepTitles[this.currentStep.stepIndex - 1];
254     this.stepsToSkip[stepTitle] = true;
255     this.onNextStep();
256   }
257 }