]> git.apps.os.sepia.ceph.com Git - ceph.git/blob
76e2970dde7faf9dd93512175042e914a9ef45f2
[ceph.git] /
1 import { Component, OnInit } from '@angular/core';
2 import { UntypedFormControl, 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, SystemKey } from '../models/rgw-multisite';
15 import { ModalService } from '~/app/shared/services/modal.service';
16
17 @Component({
18   selector: 'cd-rgw-multisite-zone-form',
19   templateUrl: './rgw-multisite-zone-form.component.html',
20   styleUrls: ['./rgw-multisite-zone-form.component.scss']
21 })
22 export class RgwMultisiteZoneFormComponent implements OnInit {
23   readonly endpoints = /^((https?:\/\/)|(www.))(?:([a-zA-Z]+)|(\d+\.\d+.\d+.\d+)):\d{2,4}$/;
24   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;
25   readonly ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;
26   action: string;
27   info: any;
28   multisiteZoneForm: CdFormGroup;
29   editing = false;
30   resource: string;
31   realm: RgwRealm;
32   zonegroup: RgwZonegroup;
33   zone: RgwZone;
34   defaultsInfo: string[] = [];
35   multisiteInfo: object[] = [];
36   zonegroupList: RgwZonegroup[] = [];
37   zoneList: RgwZone[] = [];
38   zoneNames: string[];
39   users: any;
40   placementTargets: any;
41   zoneInfo: RgwZone;
42   poolList: object[] = [];
43   storageClassList: object[] = [];
44   disableDefault: boolean = false;
45   disableMaster: boolean = false;
46   isMetadataSync: boolean = false;
47   isMasterZone: boolean;
48   isDefaultZone: boolean;
49   syncStatusTimedOut: boolean = false;
50   bsModalRef: NgbModalRef;
51   createSystemUser: boolean = false;
52   master_zone_of_master_zonegroup: RgwZone;
53   masterZoneUser: any;
54   access_key: any;
55   master_zonegroup_of_realm: RgwZonegroup;
56   compressionTypes = ['lz4', 'zlib', 'snappy'];
57   userListReady: boolean = false;
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 UntypedFormControl(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 UntypedFormControl(false),
88       master_zone: new UntypedFormControl(false),
89       selectedZonegroup: new UntypedFormControl(null),
90       zone_endpoints: new UntypedFormControl(null, {
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       access_key: new UntypedFormControl(null, Validators.required),
116       secret_key: new UntypedFormControl(null, Validators.required),
117       placementTarget: new UntypedFormControl(null),
118       placementDataPool: new UntypedFormControl(''),
119       placementIndexPool: new UntypedFormControl(null),
120       placementDataExtraPool: new UntypedFormControl(null),
121       storageClass: new UntypedFormControl(null),
122       storageDataPool: new UntypedFormControl(null),
123       storageCompression: new UntypedFormControl(null)
124     });
125   }
126
127   onZoneGroupChange(zonegroupName: string) {
128     let zg = new RgwZonegroup();
129     zg.name = zonegroupName;
130     this.rgwZoneGroupService.get(zg).subscribe((zonegroup: RgwZonegroup) => {
131       if (_.isEmpty(zonegroup.master_zone)) {
132         this.multisiteZoneForm.get('master_zone').setValue(true);
133         this.multisiteZoneForm.get('master_zone').disable();
134         this.disableMaster = false;
135       } else if (!_.isEmpty(zonegroup.master_zone) && this.action === 'create') {
136         this.multisiteZoneForm.get('master_zone').setValue(false);
137         this.multisiteZoneForm.get('master_zone').disable();
138         this.disableMaster = true;
139       }
140     });
141     if (
142       this.multisiteZoneForm.getValue('selectedZonegroup') !==
143       this.defaultsInfo['defaultZonegroupName']
144     ) {
145       this.disableDefault = true;
146       this.multisiteZoneForm.get('default_zone').disable();
147     }
148   }
149
150   ngOnInit(): void {
151     this.zonegroupList =
152       this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
153         ? this.multisiteInfo[1]['zonegroups']
154         : [];
155     this.zoneList =
156       this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
157         ? this.multisiteInfo[2]['zones']
158         : [];
159     this.zoneNames = this.zoneList.map((zone) => {
160       return zone['name'];
161     });
162     if (this.action === 'create') {
163       if (this.defaultsInfo['defaultZonegroupName'] !== undefined) {
164         this.multisiteZoneForm
165           .get('selectedZonegroup')
166           .setValue(this.defaultsInfo['defaultZonegroupName']);
167         this.onZoneGroupChange(this.defaultsInfo['defaultZonegroupName']);
168       }
169     }
170     if (this.action === 'edit') {
171       this.placementTargets = this.info.parent ? this.info.parent.data.placement_targets : [];
172       this.rgwZoneService.getPoolNames().subscribe((pools: object[]) => {
173         this.poolList = pools;
174       });
175       this.multisiteZoneForm.get('zoneName').setValue(this.info.data.name);
176       this.multisiteZoneForm.get('selectedZonegroup').setValue(this.info.data.parent);
177       this.multisiteZoneForm.get('default_zone').setValue(this.info.data.is_default);
178       this.multisiteZoneForm.get('master_zone').setValue(this.info.data.is_master);
179       this.multisiteZoneForm.get('zone_endpoints').setValue(this.info.data.endpoints.toString());
180       this.multisiteZoneForm.get('access_key').setValue(this.info.data.access_key);
181       this.multisiteZoneForm.get('secret_key').setValue(this.info.data.secret_key);
182       this.multisiteZoneForm
183         .get('placementTarget')
184         .setValue(this.info.parent.data.default_placement);
185       this.getZonePlacementData(this.multisiteZoneForm.getValue('placementTarget'));
186       if (this.info.data.is_default) {
187         this.isDefaultZone = true;
188         this.multisiteZoneForm.get('default_zone').disable();
189       }
190       if (this.info.data.is_master) {
191         this.isMasterZone = true;
192         this.multisiteZoneForm.get('master_zone').disable();
193       }
194       const zone = new RgwZone();
195       zone.name = this.info.data.name;
196       this.onZoneGroupChange(this.info.data.parent);
197     }
198     if (
199       this.multisiteZoneForm.getValue('selectedZonegroup') !==
200       this.defaultsInfo['defaultZonegroupName']
201     ) {
202       this.disableDefault = true;
203       this.multisiteZoneForm.get('default_zone').disable();
204     }
205   }
206
207   getZonePlacementData(placementTarget: string) {
208     this.zone = new RgwZone();
209     this.zone.name = this.info.data.name;
210     if (this.placementTargets) {
211       this.placementTargets.forEach((placement: any) => {
212         if (placement.name === placementTarget) {
213           let storageClasses = placement.storage_classes;
214           this.storageClassList = Object.entries(storageClasses).map(([key, value]) => ({
215             key,
216             value
217           }));
218         }
219       });
220     }
221     this.rgwZoneService.get(this.zone).subscribe((zoneInfo: RgwZone) => {
222       this.zoneInfo = zoneInfo;
223       if (this.zoneInfo && this.zoneInfo['placement_pools']) {
224         this.zoneInfo['placement_pools'].forEach((plc_pool) => {
225           if (plc_pool.key === placementTarget) {
226             let storageClasses = plc_pool.val.storage_classes;
227             let placementDataPool = storageClasses['STANDARD']
228               ? storageClasses['STANDARD']['data_pool']
229               : '';
230             let placementIndexPool = plc_pool.val.index_pool;
231             let placementDataExtraPool = plc_pool.val.data_extra_pool;
232             this.poolList.push({ poolname: placementDataPool });
233             this.poolList.push({ poolname: placementIndexPool });
234             this.poolList.push({ poolname: placementDataExtraPool });
235             this.multisiteZoneForm.get('storageClass').setValue(this.storageClassList[0]['value']);
236             this.multisiteZoneForm.get('storageDataPool').setValue(placementDataPool);
237             this.multisiteZoneForm.get('storageCompression').setValue(this.compressionTypes[0]);
238             this.multisiteZoneForm.get('placementDataPool').setValue(placementDataPool);
239             this.multisiteZoneForm.get('placementIndexPool').setValue(placementIndexPool);
240             this.multisiteZoneForm.get('placementDataExtraPool').setValue(placementDataExtraPool);
241           }
242         });
243       }
244     });
245   }
246
247   getStorageClassData(storageClass: string) {
248     let storageClassSelected = this.storageClassList.find((x) => x['value'] == storageClass)[
249       'value'
250     ];
251     this.poolList.push({ poolname: storageClassSelected.data_pool });
252     this.multisiteZoneForm.get('storageDataPool').setValue(storageClassSelected.data_pool);
253     this.multisiteZoneForm
254       .get('storageCompression')
255       .setValue(storageClassSelected.compression_type);
256   }
257
258   submit() {
259     const values = this.multisiteZoneForm.getRawValue();
260     if (this.action === 'create') {
261       this.zonegroup = new RgwZonegroup();
262       this.zonegroup.name = values['selectedZonegroup'];
263       this.zone = new RgwZone();
264       this.zone.name = values['zoneName'];
265       this.zone.endpoints = values['zone_endpoints'];
266       this.zone.system_key = new SystemKey();
267       this.zone.system_key.access_key = values['access_key'];
268       this.zone.system_key.secret_key = values['secret_key'];
269       this.rgwZoneService
270         .create(
271           this.zone,
272           this.zonegroup,
273           values['default_zone'],
274           values['master_zone'],
275           this.zone.endpoints
276         )
277         .subscribe(
278           () => {
279             this.notificationService.show(
280               NotificationType.success,
281               $localize`Zone: '${values['zoneName']}' created successfully`
282             );
283             this.activeModal.close();
284           },
285           () => {
286             this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
287           }
288         );
289     } else if (this.action === 'edit') {
290       this.zonegroup = new RgwZonegroup();
291       this.zonegroup.name = values['selectedZonegroup'];
292       this.zone = new RgwZone();
293       this.zone.name = this.info.data.name;
294       this.zone.endpoints = values['zone_endpoints'];
295       this.zone.system_key = new SystemKey();
296       this.zone.system_key.access_key = values['access_key'];
297       this.zone.system_key.secret_key = values['secret_key'];
298       this.rgwZoneService
299         .update(
300           this.zone,
301           this.zonegroup,
302           values['zoneName'],
303           values['default_zone'],
304           values['master_zone'],
305           this.zone.endpoints,
306           values['placementTarget'],
307           values['placementDataPool'],
308           values['placementIndexPool'],
309           values['placementDataExtraPool'],
310           values['storageClass'],
311           values['storageDataPool'],
312           values['storageCompression']
313         )
314         .subscribe(
315           () => {
316             this.notificationService.show(
317               NotificationType.success,
318               $localize`Zone: '${values['zoneName']}' updated successfully`
319             );
320             this.activeModal.close();
321           },
322           () => {
323             this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
324           }
325         );
326     }
327   }
328 }