]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
7a0c7ecb9835be7830776ec4effe9d95c1a3dbc5
[ceph-ci.git] /
1 import { Component, OnInit } from '@angular/core';
2 import { FormControl, Validators } from '@angular/forms';
3 import { NgbActiveModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
4 import _ from 'lodash';
5 import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
6 import { RgwUserService } from '~/app/shared/api/rgw-user.service';
7 import { RgwZoneService } from '~/app/shared/api/rgw-zone.service';
8 import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
9 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
10 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
11 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
12 import { CdValidators } from '~/app/shared/forms/cd-validators';
13 import { NotificationService } from '~/app/shared/services/notification.service';
14 import { RgwRealm, RgwZone, RgwZonegroup } from '../models/rgw-multisite';
15 import { ModalService } from '~/app/shared/services/modal.service';
16 import { RgwSystemUserComponent } from '../rgw-system-user/rgw-system-user.component';
17
18 @Component({
19   selector: 'cd-rgw-multisite-zone-form',
20   templateUrl: './rgw-multisite-zone-form.component.html',
21   styleUrls: ['./rgw-multisite-zone-form.component.scss']
22 })
23 export class RgwMultisiteZoneFormComponent implements OnInit {
24   readonly endpoints = /^((https?:\/\/)|(www.))(?:([a-zA-Z]+)|(\d+\.\d+.\d+.\d+)):\d{2,4}$/;
25   readonly ipv4Rgx = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i;
26   readonly ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;
27   action: string;
28   info: any;
29   multisiteZoneForm: CdFormGroup;
30   editing = false;
31   resource: string;
32   realm: RgwRealm;
33   zonegroup: RgwZonegroup;
34   zone: RgwZone;
35   defaultsInfo: string[] = [];
36   multisiteInfo: object[] = [];
37   zonegroupList: RgwZonegroup[] = [];
38   zoneList: RgwZone[] = [];
39   zoneNames: string[];
40   users: any;
41   placementTargets: any;
42   zoneInfo: RgwZone;
43   poolList: object[] = [];
44   storageClassList: object[] = [];
45   disableDefault: boolean = false;
46   disableMaster: boolean = false;
47   isMetadataSync: boolean = false;
48   isMasterZone: boolean;
49   isDefaultZone: boolean;
50   syncStatusTimedOut: boolean = false;
51   bsModalRef: NgbModalRef;
52   createSystemUser: boolean = false;
53   master_zone_of_master_zonegroup: RgwZone;
54   masterZoneUser: any;
55   access_key: any;
56   master_zonegroup_of_realm: RgwZonegroup;
57   compressionTypes = ['lz4', 'zlib', 'snappy'];
58
59   constructor(
60     public activeModal: NgbActiveModal,
61     public actionLabels: ActionLabelsI18n,
62     public rgwMultisiteService: RgwMultisiteService,
63     public rgwZoneService: RgwZoneService,
64     public rgwZoneGroupService: RgwZonegroupService,
65     public notificationService: NotificationService,
66     public rgwUserService: RgwUserService,
67     public modalService: ModalService
68   ) {
69     this.action = this.editing
70       ? this.actionLabels.EDIT + this.resource
71       : this.actionLabels.CREATE + this.resource;
72     this.createForm();
73   }
74
75   createForm() {
76     this.multisiteZoneForm = new CdFormGroup({
77       zoneName: new FormControl(null, {
78         validators: [
79           Validators.required,
80           CdValidators.custom('uniqueName', (zoneName: string) => {
81             return (
82               this.action === 'create' && this.zoneNames && this.zoneNames.indexOf(zoneName) !== -1
83             );
84           })
85         ]
86       }),
87       default_zone: new FormControl(false),
88       master_zone: new FormControl(false),
89       selectedZonegroup: new FormControl(null),
90       zone_endpoints: new FormControl([], {
91         validators: [
92           CdValidators.custom('endpoint', (value: string) => {
93             if (_.isEmpty(value)) {
94               return false;
95             } else {
96               if (value.includes(',')) {
97                 value.split(',').forEach((url: string) => {
98                   return (
99                     !this.endpoints.test(url) && !this.ipv4Rgx.test(url) && !this.ipv6Rgx.test(url)
100                   );
101                 });
102               } else {
103                 return (
104                   !this.endpoints.test(value) &&
105                   !this.ipv4Rgx.test(value) &&
106                   !this.ipv6Rgx.test(value)
107                 );
108               }
109               return false;
110             }
111           }),
112           Validators.required
113         ]
114       }),
115       users: new FormControl(null),
116       placementTarget: new FormControl(null),
117       placementDataPool: new FormControl(''),
118       placementIndexPool: new FormControl(null),
119       placementDataExtraPool: new FormControl(null),
120       storageClass: new FormControl(null),
121       storageDataPool: new FormControl(null),
122       storageCompression: new FormControl(null)
123     });
124   }
125
126   onZoneGroupChange(zonegroupName: string) {
127     let zg = new RgwZonegroup();
128     zg.name = zonegroupName;
129     this.rgwZoneGroupService.get(zg).subscribe((zonegroup: RgwZonegroup) => {
130       if (_.isEmpty(zonegroup.master_zone)) {
131         this.multisiteZoneForm.get('master_zone').setValue(true);
132         this.multisiteZoneForm.get('master_zone').disable();
133         this.disableMaster = false;
134       } else if (!_.isEmpty(zonegroup.master_zone) && this.action === 'create') {
135         this.multisiteZoneForm.get('master_zone').setValue(false);
136         this.multisiteZoneForm.get('master_zone').disable();
137         this.disableMaster = true;
138       }
139       const zonegroupInfo = this.zonegroupList.filter((zgroup: any) => zgroup.name === zg.name)[0];
140       if (zonegroupInfo) {
141         const realm_id = zonegroupInfo.realm_id;
142         this.master_zonegroup_of_realm = this.zonegroupList.filter(
143           (zg: any) => zg.realm_id === realm_id && zg.is_master === true
144         )[0];
145       }
146       if (this.master_zonegroup_of_realm) {
147         this.master_zone_of_master_zonegroup = this.zoneList.filter(
148           (zone: any) => zone.id === this.master_zonegroup_of_realm.master_zone
149         )[0];
150       }
151       if (this.master_zone_of_master_zonegroup) {
152         this.getUserInfo(this.master_zone_of_master_zonegroup);
153       }
154       if (zonegroupInfo.is_master && this.multisiteZoneForm.getValue('master_zone') === true) {
155         this.createSystemUser = true;
156       }
157     });
158     if (
159       this.multisiteZoneForm.getValue('selectedZonegroup') !==
160       this.defaultsInfo['defaultZonegroupName']
161     ) {
162       this.disableDefault = true;
163       this.multisiteZoneForm.get('default_zone').disable();
164     }
165   }
166
167   ngOnInit(): void {
168     this.zonegroupList =
169       this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
170         ? this.multisiteInfo[1]['zonegroups']
171         : [];
172     this.zoneList =
173       this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
174         ? this.multisiteInfo[2]['zones']
175         : [];
176     this.zoneNames = this.zoneList.map((zone) => {
177       return zone['name'];
178     });
179     if (this.action === 'create') {
180       if (this.defaultsInfo['defaultZonegroupName'] !== undefined) {
181         this.multisiteZoneForm
182           .get('selectedZonegroup')
183           .setValue(this.defaultsInfo['defaultZonegroupName']);
184         this.onZoneGroupChange(this.defaultsInfo['defaultZonegroupName']);
185       }
186     }
187     if (this.action === 'edit') {
188       this.placementTargets = this.info.parent ? this.info.parent.data.placement_targets : [];
189       this.rgwZoneService.getPoolNames().subscribe((pools: object[]) => {
190         this.poolList = pools;
191       });
192       this.multisiteZoneForm.get('zoneName').setValue(this.info.data.name);
193       this.multisiteZoneForm.get('selectedZonegroup').setValue(this.info.data.parent);
194       this.multisiteZoneForm.get('default_zone').setValue(this.info.data.is_default);
195       this.multisiteZoneForm.get('master_zone').setValue(this.info.data.is_master);
196       this.multisiteZoneForm.get('zone_endpoints').setValue(this.info.data.endpoints);
197       this.multisiteZoneForm
198         .get('placementTarget')
199         .setValue(this.info.parent.data.default_placement);
200       this.getZonePlacementData(this.multisiteZoneForm.getValue('placementTarget'));
201       if (this.info.data.is_default) {
202         this.isDefaultZone = true;
203         this.multisiteZoneForm.get('default_zone').disable();
204       }
205       if (this.info.data.is_master) {
206         this.isMasterZone = true;
207         this.multisiteZoneForm.get('master_zone').disable();
208       }
209       const zone = new RgwZone();
210       zone.name = this.info.data.name;
211       this.onZoneGroupChange(this.info.data.parent);
212       setTimeout(() => {
213         this.getUserInfo(zone);
214       }, 1500);
215     }
216     if (
217       this.multisiteZoneForm.getValue('selectedZonegroup') !==
218       this.defaultsInfo['defaultZonegroupName']
219     ) {
220       this.disableDefault = true;
221       this.multisiteZoneForm.get('default_zone').disable();
222     }
223   }
224
225   getUserInfo(zone: RgwZone) {
226     this.rgwZoneService
227       .getUserList(this.master_zone_of_master_zonegroup.name)
228       .subscribe((users: any) => {
229         this.users = users.filter((user: any) => user.keys.length !== 0);
230         this.rgwZoneService.get(zone).subscribe((zone: RgwZone) => {
231           const access_key = zone.system_key['access_key'];
232           const user = this.users.filter((user: any) => user.keys[0].access_key === access_key);
233           if (user.length > 0) {
234             this.multisiteZoneForm.get('users').setValue(user[0].user_id);
235           }
236           return user[0].user_id;
237         });
238       });
239   }
240
241   getZonePlacementData(placementTarget: string) {
242     this.zone = new RgwZone();
243     this.zone.name = this.info.data.name;
244     if (this.placementTargets) {
245       this.placementTargets.forEach((placement: any) => {
246         if (placement.name === placementTarget) {
247           let storageClasses = placement.storage_classes;
248           this.storageClassList = Object.entries(storageClasses).map(([key, value]) => ({
249             key,
250             value
251           }));
252         }
253       });
254     }
255     this.rgwZoneService.get(this.zone).subscribe((zoneInfo: RgwZone) => {
256       this.zoneInfo = zoneInfo;
257       if (this.zoneInfo && this.zoneInfo['placement_pools']) {
258         this.zoneInfo['placement_pools'].forEach((plc_pool) => {
259           if (plc_pool.key === placementTarget) {
260             let storageClasses = plc_pool.val.storage_classes;
261             let placementDataPool = storageClasses['STANDARD']
262               ? storageClasses['STANDARD']['data_pool']
263               : '';
264             let placementIndexPool = plc_pool.val.index_pool;
265             let placementDataExtraPool = plc_pool.val.data_extra_pool;
266             this.poolList.push({ poolname: placementDataPool });
267             this.poolList.push({ poolname: placementIndexPool });
268             this.poolList.push({ poolname: placementDataExtraPool });
269             this.multisiteZoneForm.get('storageClass').setValue(this.storageClassList[0]['value']);
270             this.multisiteZoneForm.get('storageDataPool').setValue(placementDataPool);
271             this.multisiteZoneForm.get('storageCompression').setValue(this.compressionTypes[0]);
272             this.multisiteZoneForm.get('placementDataPool').setValue(placementDataPool);
273             this.multisiteZoneForm.get('placementIndexPool').setValue(placementIndexPool);
274             this.multisiteZoneForm.get('placementDataExtraPool').setValue(placementDataExtraPool);
275           }
276         });
277       }
278     });
279   }
280
281   getStorageClassData(storageClass: string) {
282     let storageClassSelected = this.storageClassList.find((x) => x['value'] == storageClass)[
283       'value'
284     ];
285     this.poolList.push({ poolname: storageClassSelected.data_pool });
286     this.multisiteZoneForm.get('storageDataPool').setValue(storageClassSelected.data_pool);
287     this.multisiteZoneForm
288       .get('storageCompression')
289       .setValue(storageClassSelected.compression_type);
290   }
291
292   submit() {
293     const values = this.multisiteZoneForm.getRawValue();
294     if (this.action === 'create') {
295       this.zonegroup = new RgwZonegroup();
296       this.zonegroup.name = values['selectedZonegroup'];
297       this.zone = new RgwZone();
298       this.zone.name = values['zoneName'];
299       this.zone.endpoints = this.checkUrlArray(values['zone_endpoints']);
300       if (this.createSystemUser) {
301         values['users'] = values['zoneName'] + '_User';
302       }
303       this.rgwZoneService
304         .create(
305           this.zone,
306           this.zonegroup,
307           values['default_zone'],
308           values['master_zone'],
309           this.zone.endpoints,
310           values['users'],
311           this.createSystemUser,
312           this.master_zone_of_master_zonegroup
313         )
314         .subscribe(
315           () => {
316             this.notificationService.show(
317               NotificationType.success,
318               $localize`Zone: '${values['zoneName']}' created successfully`
319             );
320             this.activeModal.close();
321           },
322           () => {
323             this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
324           }
325         );
326     } else if (this.action === 'edit') {
327       this.zonegroup = new RgwZonegroup();
328       this.zonegroup.name = values['selectedZonegroup'];
329       this.zone = new RgwZone();
330       this.zone.name = this.info.data.name;
331       this.zone.endpoints =
332         values['zone_endpoints'] === this.info.data.endpoints
333           ? values['zonegroup_endpoints']
334           : this.checkUrlArray(values['zone_endpoints']);
335       this.rgwZoneService
336         .update(
337           this.zone,
338           this.zonegroup,
339           values['zoneName'],
340           values['default_zone'],
341           values['master_zone'],
342           this.zone.endpoints,
343           values['users'],
344           values['placementTarget'],
345           values['placementDataPool'],
346           values['placementIndexPool'],
347           values['placementDataExtraPool'],
348           values['storageClass'],
349           values['storageDataPool'],
350           values['storageCompression'],
351           this.master_zone_of_master_zonegroup
352         )
353         .subscribe(
354           () => {
355             this.notificationService.show(
356               NotificationType.success,
357               $localize`Zone: '${values['zoneName']}' updated successfully`
358             );
359             this.activeModal.close();
360           },
361           () => {
362             this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
363           }
364         );
365     }
366   }
367
368   checkUrlArray(endpoints: string) {
369     let endpointsArray = [];
370     if (endpoints.includes(',')) {
371       endpointsArray = endpoints.split(',');
372     } else {
373       endpointsArray.push(endpoints);
374     }
375     return endpointsArray;
376   }
377
378   CreateSystemUser() {
379     const initialState = {
380       zoneName: this.master_zone_of_master_zonegroup.name
381     };
382     this.bsModalRef = this.modalService.show(RgwSystemUserComponent, initialState);
383     this.bsModalRef.componentInstance.submitAction.subscribe(() => {
384       this.getUserInfo(this.master_zone_of_master_zonegroup);
385     });
386   }
387 }