]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
a07e45d11ac77ec165d7176db1888ac545d5fdde
[ceph-ci.git] /
1 import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
2 import {
3   TreeComponent,
4   ITreeOptions,
5   TreeModel,
6   TreeNode,
7   TREE_ACTIONS
8 } from '@circlon/angular-tree-component';
9 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
10 import _ from 'lodash';
11 import { forkJoin, Subscription } from 'rxjs';
12 import { RgwRealmService } from '~/app/shared/api/rgw-realm.service';
13 import { RgwZoneService } from '~/app/shared/api/rgw-zone.service';
14 import { RgwZonegroupService } from '~/app/shared/api/rgw-zonegroup.service';
15 import { ActionLabelsI18n, TimerServiceInterval } from '~/app/shared/constants/app.constants';
16 import { Icons } from '~/app/shared/enum/icons.enum';
17 import { CdTableAction } from '~/app/shared/models/cd-table-action';
18 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
19 import { Permission } from '~/app/shared/models/permissions';
20 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
21 import { ModalService } from '~/app/shared/services/modal.service';
22 import { TimerService } from '~/app/shared/services/timer.service';
23 import { RgwRealm, RgwZone, RgwZonegroup } from '../models/rgw-multisite';
24 import { RgwMultisiteRealmFormComponent } from '../rgw-multisite-realm-form/rgw-multisite-realm-form.component';
25 import { RgwMultisiteZoneFormComponent } from '../rgw-multisite-zone-form/rgw-multisite-zone-form.component';
26 import { RgwMultisiteZonegroupFormComponent } from '../rgw-multisite-zonegroup-form/rgw-multisite-zonegroup-form.component';
27
28 @Component({
29   selector: 'cd-rgw-multisite-details',
30   templateUrl: './rgw-multisite-details.component.html',
31   styleUrls: ['./rgw-multisite-details.component.scss']
32 })
33 export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit {
34   private sub = new Subscription();
35
36   @ViewChild('tree') tree: TreeComponent;
37
38   messages = {
39     noDefaultRealm: $localize`Please create a default realm first to enable this feature`,
40     noMasterZone: $localize`Please create a master zone for each zonegroups to enable this feature`
41   };
42
43   icons = Icons;
44   permission: Permission;
45   selection = new CdTableSelection();
46   createTableActions: CdTableAction[];
47   loadingIndicator = true;
48   nodes: object[] = [];
49   treeOptions: ITreeOptions = {
50     useVirtualScroll: true,
51     nodeHeight: 22,
52     levelPadding: 20,
53     actionMapping: {
54       mouse: {
55         click: this.onNodeSelected.bind(this)
56       }
57     }
58   };
59
60   realms: RgwRealm[] = [];
61   zonegroups: RgwZonegroup[] = [];
62   zones: RgwZone[] = [];
63   metadata: any;
64   metadataTitle: string;
65   bsModalRef: NgbModalRef;
66   realmIds: string[] = [];
67   zoneIds: string[] = [];
68   defaultRealmId = '';
69   defaultZonegroupId = '';
70   defaultZoneId = '';
71   multisiteInfo: object[] = [];
72   defaultsInfo: string[] = [];
73
74   constructor(
75     private modalService: ModalService,
76     private timerService: TimerService,
77     private authStorageService: AuthStorageService,
78     public actionLabels: ActionLabelsI18n,
79     public timerServiceVariable: TimerServiceInterval,
80     public rgwRealmService: RgwRealmService,
81     public rgwZonegroupService: RgwZonegroupService,
82     public rgwZoneService: RgwZoneService
83   ) {
84     this.permission = this.authStorageService.getPermissions().rgw;
85     const createRealmAction: CdTableAction = {
86       permission: 'create',
87       icon: Icons.add,
88       name: this.actionLabels.CREATE + ' Realm',
89       click: () => this.openModal('realm')
90     };
91     const createZonegroupAction: CdTableAction = {
92       permission: 'create',
93       icon: Icons.add,
94       name: this.actionLabels.CREATE + ' Zonegroup',
95       click: () => this.openModal('zonegroup'),
96       disable: () => this.getDisable()
97     };
98     const createZoneAction: CdTableAction = {
99       permission: 'create',
100       icon: Icons.add,
101       name: this.actionLabels.CREATE + ' Zone',
102       click: () => this.openModal('zone')
103     };
104     this.createTableActions = [createRealmAction, createZonegroupAction, createZoneAction];
105   }
106
107   openModal(entity: any, edit = false) {
108     const entityName = edit ? entity.data.type : entity;
109     const action = edit ? 'edit' : 'create';
110     const initialState = {
111       resource: entityName,
112       action: action,
113       info: entity,
114       defaultsInfo: this.defaultsInfo,
115       multisiteInfo: this.multisiteInfo
116     };
117     if (entityName === 'realm') {
118       this.bsModalRef = this.modalService.show(RgwMultisiteRealmFormComponent, initialState, {
119         size: 'lg'
120       });
121     } else if (entityName === 'zonegroup') {
122       this.bsModalRef = this.modalService.show(RgwMultisiteZonegroupFormComponent, initialState, {
123         size: 'lg'
124       });
125     } else {
126       this.bsModalRef = this.modalService.show(RgwMultisiteZoneFormComponent, initialState, {
127         size: 'lg'
128       });
129     }
130   }
131
132   ngOnInit() {
133     const observables = [
134       this.rgwRealmService.getAllRealmsInfo(),
135       this.rgwZonegroupService.getAllZonegroupsInfo(),
136       this.rgwZoneService.getAllZonesInfo()
137     ];
138     this.sub = this.timerService
139       .get(() => forkJoin(observables), this.timerServiceVariable.TIMER_SERVICE_PERIOD * 2)
140       .subscribe(
141         (multisiteInfo: [object, object, object]) => {
142           this.multisiteInfo = multisiteInfo;
143           this.loadingIndicator = false;
144           this.nodes = this.abstractTreeData(multisiteInfo);
145         },
146         (_error) => {}
147       );
148   }
149
150   ngOnDestroy() {
151     this.sub.unsubscribe();
152   }
153
154   private abstractTreeData(multisiteInfo: [object, object, object]): any[] {
155     let allNodes: object[] = [];
156     let rootNodes = {};
157     let firstChildNodes = {};
158     let allFirstChildNodes = [];
159     let secondChildNodes = {};
160     let allSecondChildNodes: {}[] = [];
161     this.realms = multisiteInfo[0]['realms'];
162     this.zonegroups = multisiteInfo[1]['zonegroups'];
163     this.zones = multisiteInfo[2]['zones'];
164     this.defaultRealmId = multisiteInfo[0]['default_realm'];
165     this.defaultZonegroupId = multisiteInfo[1]['default_zonegroup'];
166     this.defaultZoneId = multisiteInfo[2]['default_zone'];
167     this.defaultsInfo = this.getDefaultsEntities(
168       this.defaultRealmId,
169       this.defaultZonegroupId,
170       this.defaultZoneId
171     );
172     if (this.realms.length > 0) {
173       // get tree for realm -> zonegroup -> zone
174       for (const realm of this.realms) {
175         const result = this.rgwRealmService.getRealmTree(realm, this.defaultRealmId);
176         rootNodes = result['nodes'];
177         this.realmIds = this.realmIds.concat(result['realmIds']);
178         for (const zonegroup of this.zonegroups) {
179           if (zonegroup.realm_id === realm.id) {
180             firstChildNodes = this.rgwZonegroupService.getZonegroupTree(
181               zonegroup,
182               this.defaultZonegroupId,
183               realm
184             );
185             for (const zone of zonegroup.zones) {
186               const zoneResult = this.rgwZoneService.getZoneTree(
187                 zone,
188                 this.defaultZoneId,
189                 zonegroup,
190                 realm
191               );
192               secondChildNodes = zoneResult['nodes'];
193               this.zoneIds = this.zoneIds.concat(zoneResult['zoneIds']);
194               allSecondChildNodes.push(secondChildNodes);
195               secondChildNodes = {};
196             }
197             firstChildNodes['children'] = allSecondChildNodes;
198             allSecondChildNodes = [];
199             allFirstChildNodes.push(firstChildNodes);
200             firstChildNodes = {};
201           }
202         }
203         rootNodes['children'] = allFirstChildNodes;
204         allNodes.push(rootNodes);
205         firstChildNodes = {};
206         secondChildNodes = {};
207         rootNodes = {};
208         allFirstChildNodes = [];
209         allSecondChildNodes = [];
210       }
211     }
212     if (this.zonegroups.length > 0) {
213       // get tree for zonegroup -> zone (standalone zonegroups that don't match a realm eg(initial default))
214       for (const zonegroup of this.zonegroups) {
215         if (!this.realmIds.includes(zonegroup.realm_id)) {
216           rootNodes = this.rgwZonegroupService.getZonegroupTree(zonegroup, this.defaultZonegroupId);
217           for (const zone of zonegroup.zones) {
218             const zoneResult = this.rgwZoneService.getZoneTree(zone, this.defaultZoneId, zonegroup);
219             firstChildNodes = zoneResult['nodes'];
220             this.zoneIds = this.zoneIds.concat(zoneResult['zoneIds']);
221             allFirstChildNodes.push(firstChildNodes);
222             firstChildNodes = {};
223           }
224           rootNodes['children'] = allFirstChildNodes;
225           allNodes.push(rootNodes);
226           firstChildNodes = {};
227           rootNodes = {};
228           allFirstChildNodes = [];
229         }
230       }
231     }
232     if (this.zones.length > 0) {
233       // get tree for standalone zones(zones that do not belong to a zonegroup)
234       for (const zone of this.zones) {
235         if (this.zoneIds.length > 0 && !this.zoneIds.includes(zone.id)) {
236           const zoneResult = this.rgwZoneService.getZoneTree(zone, this.defaultZoneId);
237           rootNodes = zoneResult['nodes'];
238           allNodes.push(rootNodes);
239           rootNodes = {};
240         }
241       }
242     }
243     if (this.realms.length < 1 && this.zonegroups.length < 1 && this.zones.length < 1) {
244       return [
245         {
246           name: 'No nodes!'
247         }
248       ];
249     }
250     this.realmIds = [];
251     this.zoneIds = [];
252     return allNodes;
253   }
254
255   getDefaultsEntities(
256     defaultRealmId: string,
257     defaultZonegroupId: string,
258     defaultZoneId: string
259   ): any {
260     const defaultRealm = this.realms.find((x: { id: string }) => x.id === defaultRealmId);
261     const defaultZonegroup = this.zonegroups.find(
262       (x: { id: string }) => x.id === defaultZonegroupId
263     );
264     const defaultZone = this.zones.find((x: { id: string }) => x.id === defaultZoneId);
265     const defaultRealmName = defaultRealm !== undefined ? defaultRealm.name : null;
266     const defaultZonegroupName = defaultZonegroup !== undefined ? defaultZonegroup.name : null;
267     const defaultZoneName = defaultZone !== undefined ? defaultZone.name : null;
268     return {
269       defaultRealmName: defaultRealmName,
270       defaultZonegroupName: defaultZonegroupName,
271       defaultZoneName: defaultZoneName
272     };
273   }
274
275   onNodeSelected(tree: TreeModel, node: TreeNode) {
276     TREE_ACTIONS.ACTIVATE(tree, node, true);
277     this.metadataTitle = node.data.name;
278     this.metadata = node.data.info;
279     node.data.show = true;
280   }
281
282   onUpdateData() {
283     this.tree.treeModel.expandAll();
284   }
285
286   getDisable() {
287     if (this.defaultRealmId === '') {
288       return this.messages.noDefaultRealm;
289     } else {
290       let isMasterZone = true;
291       this.zonegroups.forEach((zgp: any) => {
292         if (_.isEmpty(zgp.master_zone)) {
293           isMasterZone = false;
294         }
295       });
296       if (!isMasterZone) {
297         return this.messages.noMasterZone;
298       } else {
299         return false;
300       }
301     }
302   }
303 }