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';
19 selector: 'cd-rgw-multisite-zone-form',
20 templateUrl: './rgw-multisite-zone-form.component.html',
21 styleUrls: ['./rgw-multisite-zone-form.component.scss']
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;
29 multisiteZoneForm: CdFormGroup;
33 zonegroup: RgwZonegroup;
35 defaultsInfo: string[] = [];
36 multisiteInfo: object[] = [];
37 zonegroupList: RgwZonegroup[] = [];
38 zoneList: RgwZone[] = [];
41 placementTargets: any;
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;
56 master_zonegroup_of_realm: RgwZonegroup;
57 compressionTypes = ['lz4', 'zlib', 'snappy'];
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
69 this.action = this.editing
70 ? this.actionLabels.EDIT + this.resource
71 : this.actionLabels.CREATE + this.resource;
76 this.multisiteZoneForm = new CdFormGroup({
77 zoneName: new FormControl(null, {
80 CdValidators.custom('uniqueName', (zoneName: string) => {
82 this.action === 'create' && this.zoneNames && this.zoneNames.indexOf(zoneName) !== -1
87 default_zone: new FormControl(false),
88 master_zone: new FormControl(false),
89 selectedZonegroup: new FormControl(null),
90 zone_endpoints: new FormControl([], {
92 CdValidators.custom('endpoint', (value: string) => {
93 if (_.isEmpty(value)) {
96 if (value.includes(',')) {
97 value.split(',').forEach((url: string) => {
99 !this.endpoints.test(url) && !this.ipv4Rgx.test(url) && !this.ipv6Rgx.test(url)
104 !this.endpoints.test(value) &&
105 !this.ipv4Rgx.test(value) &&
106 !this.ipv6Rgx.test(value)
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)
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;
139 const zonegroupInfo = this.zonegroupList.filter((zgroup: any) => zgroup.name === zg.name)[0];
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
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
151 if (this.master_zone_of_master_zonegroup) {
152 this.getUserInfo(this.master_zone_of_master_zonegroup);
154 if (zonegroupInfo.is_master && this.multisiteZoneForm.getValue('master_zone') === true) {
155 this.createSystemUser = true;
159 this.multisiteZoneForm.getValue('selectedZonegroup') !==
160 this.defaultsInfo['defaultZonegroupName']
162 this.disableDefault = true;
163 this.multisiteZoneForm.get('default_zone').disable();
169 this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
170 ? this.multisiteInfo[1]['zonegroups']
173 this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
174 ? this.multisiteInfo[2]['zones']
176 this.zoneNames = this.zoneList.map((zone) => {
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']);
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;
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();
205 if (this.info.data.is_master) {
206 this.isMasterZone = true;
207 this.multisiteZoneForm.get('master_zone').disable();
209 const zone = new RgwZone();
210 zone.name = this.info.data.name;
211 this.onZoneGroupChange(this.info.data.parent);
213 this.getUserInfo(zone);
217 this.multisiteZoneForm.getValue('selectedZonegroup') !==
218 this.defaultsInfo['defaultZonegroupName']
220 this.disableDefault = true;
221 this.multisiteZoneForm.get('default_zone').disable();
225 getUserInfo(zone: RgwZone) {
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);
236 return user[0].user_id;
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]) => ({
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']
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);
281 getStorageClassData(storageClass: string) {
282 let storageClassSelected = this.storageClassList.find((x) => x['value'] == storageClass)[
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);
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';
307 values['default_zone'],
308 values['master_zone'],
311 this.createSystemUser,
312 this.master_zone_of_master_zonegroup
316 this.notificationService.show(
317 NotificationType.success,
318 $localize`Zone: '${values['zoneName']}' created successfully`
320 this.activeModal.close();
323 this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
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']);
340 values['default_zone'],
341 values['master_zone'],
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
355 this.notificationService.show(
356 NotificationType.success,
357 $localize`Zone: '${values['zoneName']}' updated successfully`
359 this.activeModal.close();
362 this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
368 checkUrlArray(endpoints: string) {
369 let endpointsArray = [];
370 if (endpoints.includes(',')) {
371 endpointsArray = endpoints.split(',');
373 endpointsArray.push(endpoints);
375 return endpointsArray;
379 const initialState = {
380 zoneName: this.master_zone_of_master_zonegroup.name
382 this.bsModalRef = this.modalService.show(RgwSystemUserComponent, initialState);
383 this.bsModalRef.componentInstance.submitAction.subscribe(() => {
384 this.getUserInfo(this.master_zone_of_master_zonegroup);