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';
18 selector: 'cd-rgw-multisite-zone-form',
19 templateUrl: './rgw-multisite-zone-form.component.html',
20 styleUrls: ['./rgw-multisite-zone-form.component.scss']
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;
28 multisiteZoneForm: CdFormGroup;
32 zonegroup: RgwZonegroup;
34 defaultsInfo: string[] = [];
35 multisiteInfo: object[] = [];
36 zonegroupList: RgwZonegroup[] = [];
37 zoneList: RgwZone[] = [];
40 placementTargets: any;
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;
55 master_zonegroup_of_realm: RgwZonegroup;
56 compressionTypes = ['lz4', 'zlib', 'snappy'];
57 userListReady: boolean = false;
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 UntypedFormControl(null, {
80 CdValidators.custom('uniqueName', (zoneName: string) => {
82 this.action === 'create' && this.zoneNames && this.zoneNames.indexOf(zoneName) !== -1
87 default_zone: new UntypedFormControl(false),
88 master_zone: new UntypedFormControl(false),
89 selectedZonegroup: new UntypedFormControl(null),
90 zone_endpoints: new UntypedFormControl(null, {
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 access_key: new UntypedFormControl('', {}),
116 secret_key: new UntypedFormControl('', {}),
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)
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;
142 this.multisiteZoneForm.getValue('selectedZonegroup') !==
143 this.defaultsInfo['defaultZonegroupName']
145 this.disableDefault = true;
146 this.multisiteZoneForm.get('default_zone').disable();
152 this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
153 ? this.multisiteInfo[1]['zonegroups']
156 this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
157 ? this.multisiteInfo[2]['zones']
159 this.zoneNames = this.zoneList.map((zone) => {
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']);
170 if (this.action === 'edit') {
171 this.placementTargets =
172 this.info.data?.parent || this.info.parent
173 ? (this.info.data?.parentNode || this.info.parent.data)?.placement_targets
175 this.rgwZoneService.getPoolNames().subscribe((pools: object[]) => {
176 this.poolList = pools;
178 this.multisiteZoneForm.get('zoneName').setValue(this.info.data.name);
179 this.multisiteZoneForm.get('selectedZonegroup').setValue(this.info.data.parent);
180 this.multisiteZoneForm.get('default_zone').setValue(this.info.data.is_default);
181 this.multisiteZoneForm.get('master_zone').setValue(this.info.data.is_master);
182 this.multisiteZoneForm.get('zone_endpoints').setValue(this.info.data.endpoints.toString());
183 this.multisiteZoneForm.get('access_key').setValue(this.info.data.access_key);
184 this.multisiteZoneForm.get('secret_key').setValue(this.info.data.secret_key);
185 this.multisiteZoneForm
186 .get('placementTarget')
187 .setValue((this.info.data?.parentNode || this.info.parent.data)?.default_placement);
188 this.getZonePlacementData(this.multisiteZoneForm.getValue('placementTarget'));
189 if (this.info.data.is_default) {
190 this.isDefaultZone = true;
191 this.multisiteZoneForm.get('default_zone').disable();
193 if (this.info.data.is_master) {
194 this.isMasterZone = true;
195 this.multisiteZoneForm.get('master_zone').disable();
197 const zone = new RgwZone();
198 zone.name = this.info.data.name;
199 this.onZoneGroupChange(this.info.data.parent);
202 this.multisiteZoneForm.getValue('selectedZonegroup') !==
203 this.defaultsInfo['defaultZonegroupName']
205 this.disableDefault = true;
206 this.multisiteZoneForm.get('default_zone').disable();
210 getZonePlacementData(placementTarget: string) {
211 this.zone = new RgwZone();
212 this.zone.name = this.info.data.name;
213 this.rgwZoneService.get(this.zone).subscribe((zoneInfo: RgwZone) => {
214 this.zoneInfo = zoneInfo;
215 if (this.zoneInfo && this.zoneInfo['placement_pools']) {
216 const placementPoolKeys = this.zoneInfo['placement_pools'].map((plc_pool) => plc_pool.key);
217 this.placementTargets = this.placementTargets.filter((placement: { name: string }) =>
218 placementPoolKeys.includes(placement.name)
220 this.zoneInfo['placement_pools'].forEach((plc_pool) => {
221 if (plc_pool.key === placementTarget) {
222 let storageClasses = plc_pool.val.storage_classes;
223 this.storageClassList = Object.entries(storageClasses).map(([key, value]) => ({
227 let placementDataPool = storageClasses['STANDARD']
228 ? storageClasses['STANDARD']['data_pool']
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]['key']);
236 this.getStorageClassData(this.storageClassList[0]['key']);
237 this.multisiteZoneForm.get('placementDataPool').setValue(placementDataPool);
238 this.multisiteZoneForm.get('placementIndexPool').setValue(placementIndexPool);
239 this.multisiteZoneForm.get('placementDataExtraPool').setValue(placementDataExtraPool);
246 getStorageClassData(storageClass: string) {
247 let storageClassSelected = this.storageClassList.find((sc) => sc['key'] === storageClass);
248 this.poolList.push({ poolname: storageClassSelected['value']['data_pool'] });
249 this.multisiteZoneForm
250 .get('storageDataPool')
251 .setValue(storageClassSelected['value']['data_pool']);
252 this.multisiteZoneForm
253 .get('storageCompression')
254 .setValue(storageClassSelected['value']['compression_type']);
258 const values = this.multisiteZoneForm.getRawValue();
259 if (this.action === 'create') {
260 this.zonegroup = new RgwZonegroup();
261 this.zonegroup.name = values['selectedZonegroup'];
262 this.zone = new RgwZone();
263 this.zone.name = values['zoneName'];
264 this.zone.endpoints = values['zone_endpoints'];
265 this.zone.system_key = new SystemKey();
266 this.zone.system_key.access_key = values['access_key'];
267 this.zone.system_key.secret_key = values['secret_key'];
272 values['default_zone'],
273 values['master_zone'],
278 this.notificationService.show(
279 NotificationType.success,
280 $localize`Zone: '${values['zoneName']}' created successfully`
282 this.activeModal.close();
285 this.multisiteZoneForm.setErrors({ cdSubmitButton: true });
288 } else if (this.action === 'edit') {
289 this.zonegroup = new RgwZonegroup();
290 this.zonegroup.name = values['selectedZonegroup'];
291 this.zone = new RgwZone();
292 this.zone.name = this.info.data.name;
293 this.zone.endpoints = values['zone_endpoints'];
294 this.zone.system_key = new SystemKey();
295 this.zone.system_key.access_key = values['access_key'];
296 this.zone.system_key.secret_key = values['secret_key'];
302 values['default_zone'],
303 values['master_zone'],
305 values['placementTarget'],
306 values['placementDataPool'],
307 values['placementIndexPool'],
308 values['placementDataExtraPool'],
309 values['storageClass'],
310 values['storageDataPool'],
311 values['storageCompression']
315 this.notificationService.show(
316 NotificationType.success,
317 $localize`Zone: '${values['zoneName']}' updated successfully`
319 this.activeModal.close();
322 this.multisiteZoneForm.setErrors({ cdSubmitButton: true });