]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zonegroup-form/rgw-multisite-zonegroup-form.component.ts
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / rgw / rgw-multisite-zonegroup-form / rgw-multisite-zonegroup-form.component.ts
1 import { Component, OnInit } from '@angular/core';
2 import {
3 UntypedFormArray,
4 UntypedFormBuilder,
5 UntypedFormControl,
6 NgForm,
7 Validators
8 } from '@angular/forms';
9 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
10 import _ from 'lodash';
11 import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
12 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
13 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
14 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
15 import { CdValidators } from '~/app/shared/forms/cd-validators';
16 import { NotificationService } from '~/app/shared/services/notification.service';
17 import { RgwRealm, RgwZone, RgwZonegroup } from '../models/rgw-multisite';
18 import { Icons } from '~/app/shared/enum/icons.enum';
19 import { SelectOption } from '~/app/shared/components/select/select-option.model';
20
21 @Component({
22 selector: 'cd-rgw-multisite-zonegroup-form',
23 templateUrl: './rgw-multisite-zonegroup-form.component.html',
24 styleUrls: ['./rgw-multisite-zonegroup-form.component.scss']
25 })
26 export class RgwMultisiteZonegroupFormComponent implements OnInit {
27 readonly endpoints = /^((https?:\/\/)|(www.))(?:([a-zA-Z]+)|(\d+\.\d+.\d+.\d+)):\d{2,4}$/;
28 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;
29 readonly ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;
30 action: string;
31 icons = Icons;
32 multisiteZonegroupForm: CdFormGroup;
33 editing = false;
34 resource: string;
35 realm: RgwRealm;
36 zonegroup: RgwZonegroup;
37 info: any;
38 defaultsInfo: string[] = [];
39 multisiteInfo: object[] = [];
40 realmList: RgwRealm[] = [];
41 zonegroupList: RgwZonegroup[] = [];
42 zonegroupNames: string[];
43 isMaster = false;
44 placementTargets: UntypedFormArray;
45 newZonegroupName: string;
46 zonegroupZoneNames: string[];
47 labelsOption: Array<SelectOption> = [];
48 zoneList: RgwZone[] = [];
49 allZoneNames: string[];
50 zgZoneNames: string[];
51 zgZoneIds: string[];
52 removedZones: string[];
53 isRemoveMasterZone = false;
54 addedZones: string[];
55 disableDefault = false;
56 disableMaster = false;
57
58 constructor(
59 public activeModal: NgbActiveModal,
60 public actionLabels: ActionLabelsI18n,
61 public rgwZonegroupService: RgwZonegroupService,
62 public notificationService: NotificationService,
63 private formBuilder: UntypedFormBuilder
64 ) {
65 this.action = this.editing
66 ? this.actionLabels.EDIT + this.resource
67 : this.actionLabels.CREATE + this.resource;
68 this.createForm();
69 }
70
71 createForm() {
72 this.multisiteZonegroupForm = new CdFormGroup({
73 default_zonegroup: new UntypedFormControl(false),
74 zonegroupName: new UntypedFormControl(null, {
75 validators: [
76 Validators.required,
77 CdValidators.custom('uniqueName', (zonegroupName: string) => {
78 return (
79 this.action === 'create' &&
80 this.zonegroupNames &&
81 this.zonegroupNames.indexOf(zonegroupName) !== -1
82 );
83 })
84 ]
85 }),
86 master_zonegroup: new UntypedFormControl(false),
87 selectedRealm: new UntypedFormControl(null),
88 zonegroup_endpoints: new UntypedFormControl(null, [
89 CdValidators.custom('endpoint', (value: string) => {
90 if (_.isEmpty(value)) {
91 return false;
92 } else {
93 if (value.includes(',')) {
94 value.split(',').forEach((url: string) => {
95 return (
96 !this.endpoints.test(url) && !this.ipv4Rgx.test(url) && !this.ipv6Rgx.test(url)
97 );
98 });
99 } else {
100 return (
101 !this.endpoints.test(value) &&
102 !this.ipv4Rgx.test(value) &&
103 !this.ipv6Rgx.test(value)
104 );
105 }
106 return false;
107 }
108 }),
109 Validators.required
110 ]),
111 placementTargets: this.formBuilder.array([])
112 });
113 }
114
115 ngOnInit(): void {
116 _.forEach(this.multisiteZonegroupForm.get('placementTargets'), (placementTarget) => {
117 const fg = this.addPlacementTarget();
118 fg.patchValue(placementTarget);
119 });
120 this.placementTargets = this.multisiteZonegroupForm.get('placementTargets') as UntypedFormArray;
121 this.realmList =
122 this.multisiteInfo[0] !== undefined && this.multisiteInfo[0].hasOwnProperty('realms')
123 ? this.multisiteInfo[0]['realms']
124 : [];
125 this.zonegroupList =
126 this.multisiteInfo[1] !== undefined && this.multisiteInfo[1].hasOwnProperty('zonegroups')
127 ? this.multisiteInfo[1]['zonegroups']
128 : [];
129 this.zonegroupList.forEach((zgp: any) => {
130 if (zgp.is_master === true && !_.isEmpty(zgp.realm_id)) {
131 this.isMaster = true;
132 this.disableMaster = true;
133 }
134 });
135 if (!this.isMaster) {
136 this.multisiteZonegroupForm.get('master_zonegroup').setValue(true);
137 this.multisiteZonegroupForm.get('master_zonegroup').disable();
138 }
139 this.zoneList =
140 this.multisiteInfo[2] !== undefined && this.multisiteInfo[2].hasOwnProperty('zones')
141 ? this.multisiteInfo[2]['zones']
142 : [];
143 this.zonegroupNames = this.zonegroupList.map((zonegroup) => {
144 return zonegroup['name'];
145 });
146 let allZonegroupZonesList = this.zonegroupList.map((zonegroup: RgwZonegroup) => {
147 return zonegroup['zones'];
148 });
149 const allZonegroupZonesInfo = allZonegroupZonesList.reduce(
150 (accumulator, value) => accumulator.concat(value),
151 []
152 );
153 const allZonegroupZonesNames = allZonegroupZonesInfo.map((zone) => {
154 return zone['name'];
155 });
156 this.allZoneNames = this.zoneList.map((zone: RgwZone) => {
157 return zone['name'];
158 });
159 this.allZoneNames = _.difference(this.allZoneNames, allZonegroupZonesNames);
160 if (this.action === 'create' && this.defaultsInfo['defaultRealmName'] !== null) {
161 this.multisiteZonegroupForm
162 .get('selectedRealm')
163 .setValue(this.defaultsInfo['defaultRealmName']);
164 if (this.disableMaster) {
165 this.multisiteZonegroupForm.get('master_zonegroup').disable();
166 }
167 }
168 if (this.action === 'edit') {
169 this.multisiteZonegroupForm.get('zonegroupName').setValue(this.info.data.name);
170 this.multisiteZonegroupForm.get('selectedRealm').setValue(this.info.data.parent);
171 this.multisiteZonegroupForm.get('default_zonegroup').setValue(this.info.data.is_default);
172 this.multisiteZonegroupForm.get('master_zonegroup').setValue(this.info.data.is_master);
173 this.multisiteZonegroupForm.get('zonegroup_endpoints').setValue(this.info.data.endpoints);
174
175 if (this.info.data.is_default) {
176 this.multisiteZonegroupForm.get('default_zonegroup').disable();
177 }
178 if (
179 !this.info.data.is_default &&
180 this.multisiteZonegroupForm.getValue('selectedRealm') !==
181 this.defaultsInfo['defaultRealmName']
182 ) {
183 this.multisiteZonegroupForm.get('default_zonegroup').disable();
184 this.disableDefault = true;
185 }
186 if (this.info.data.is_master || this.disableMaster) {
187 this.multisiteZonegroupForm.get('master_zonegroup').disable();
188 }
189
190 this.zonegroupZoneNames = this.info.data.zones.map((zone: { [x: string]: any }) => {
191 return zone['name'];
192 });
193 this.zgZoneNames = this.info.data.zones.map((zone: { [x: string]: any }) => {
194 return zone['name'];
195 });
196 this.zgZoneIds = this.info.data.zones.map((zone: { [x: string]: any }) => {
197 return zone['id'];
198 });
199 const uniqueZones = new Set(this.allZoneNames);
200 this.labelsOption = Array.from(uniqueZones).map((zone) => {
201 return { enabled: true, name: zone, selected: false, description: null };
202 });
203
204 this.info.data.placement_targets.forEach((target: object) => {
205 const fg = this.addPlacementTarget();
206 let data = {
207 placement_id: target['name'],
208 tags: target['tags'].join(','),
209 storage_class:
210 typeof target['storage_classes'] === 'string'
211 ? target['storage_classes']
212 : target['storage_classes'].join(',')
213 };
214 fg.patchValue(data);
215 });
216 }
217 }
218
219 submit() {
220 const values = this.multisiteZonegroupForm.getRawValue();
221 if (this.action === 'create') {
222 this.realm = new RgwRealm();
223 this.realm.name = values['selectedRealm'];
224 this.zonegroup = new RgwZonegroup();
225 this.zonegroup.name = values['zonegroupName'];
226 this.zonegroup.endpoints = values['zonegroup_endpoints'];
227 this.rgwZonegroupService
228 .create(this.realm, this.zonegroup, values['default_zonegroup'], values['master_zonegroup'])
229 .subscribe(
230 () => {
231 this.notificationService.show(
232 NotificationType.success,
233 $localize`Zonegroup: '${values['zonegroupName']}' created successfully`
234 );
235 this.activeModal.close();
236 },
237 () => {
238 this.multisiteZonegroupForm.setErrors({ cdSubmitButton: true });
239 }
240 );
241 } else if (this.action === 'edit') {
242 this.removedZones = _.difference(this.zgZoneNames, this.zonegroupZoneNames);
243 const masterZoneName = this.info.data.zones.filter(
244 (zone: any) => zone.id === this.info.data.master_zone
245 );
246 this.isRemoveMasterZone = this.removedZones.includes(masterZoneName[0].name);
247 if (this.isRemoveMasterZone) {
248 this.multisiteZonegroupForm.setErrors({ cdSubmitButton: true });
249 return;
250 }
251 this.addedZones = _.difference(this.zonegroupZoneNames, this.zgZoneNames);
252 this.realm = new RgwRealm();
253 this.realm.name = values['selectedRealm'];
254 this.zonegroup = new RgwZonegroup();
255 this.zonegroup.name = this.info.data.name;
256 this.newZonegroupName = values['zonegroupName'];
257 this.zonegroup.endpoints = values['zonegroup_endpoints'].toString();
258 this.zonegroup.placement_targets = values['placementTargets'];
259 this.rgwZonegroupService
260 .update(
261 this.realm,
262 this.zonegroup,
263 this.newZonegroupName,
264 values['default_zonegroup'],
265 values['master_zonegroup'],
266 this.removedZones,
267 this.addedZones
268 )
269 .subscribe(
270 () => {
271 this.notificationService.show(
272 NotificationType.success,
273 $localize`Zonegroup: '${values['zonegroupName']}' updated successfully`
274 );
275 this.activeModal.close();
276 },
277 () => {
278 this.multisiteZonegroupForm.setErrors({ cdSubmitButton: true });
279 }
280 );
281 }
282 }
283
284 addPlacementTarget() {
285 this.placementTargets = this.multisiteZonegroupForm.get('placementTargets') as UntypedFormArray;
286 const fg = new CdFormGroup({
287 placement_id: new UntypedFormControl('', {
288 validators: [Validators.required]
289 }),
290 tags: new UntypedFormControl(''),
291 storage_class: new UntypedFormControl([])
292 });
293 this.placementTargets.push(fg);
294 return fg;
295 }
296
297 trackByFn(index: number) {
298 return index;
299 }
300
301 removePlacementTarget(index: number) {
302 this.placementTargets = this.multisiteZonegroupForm.get('placementTargets') as UntypedFormArray;
303 this.placementTargets.removeAt(index);
304 }
305
306 showError(index: number, control: string, formDir: NgForm, x: string) {
307 return (<any>this.multisiteZonegroupForm.controls.placementTargets).controls[index].showError(
308 control,
309 formDir,
310 x
311 );
312 }
313 }