Fix Bug 2336: Manual Healing option in Ui
[osm/NG-UI.git] / src / app / utilities / ns-instances-action / NSInstancesActionComponent.ts
1 /*
2  Copyright 2020 TATA ELXSI
3
4  Licensed under the Apache License, Version 2.0 (the 'License');
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8   http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17 */
18 /**
19  * @file NS InstancesAction Component
20  */
21 import { isNullOrUndefined } from 'util';
22 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector } from '@angular/core';
23 import { Router } from '@angular/router';
24 import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
25 import { TranslateService } from '@ngx-translate/core';
26 import { NotifierService } from 'angular-notifier';
27 import { ERRORDATA, MODALCLOSERESPONSEDATA } from 'CommonModel';
28 import { DeleteComponent } from 'DeleteComponent';
29 import { environment } from 'environment';
30 import { HealingComponent } from 'HealingComponent';
31 import { NSDDetails } from 'NSDModel';
32 import { NSDInstanceData } from 'NSInstanceModel';
33 import { NSPrimitiveComponent } from 'NSPrimitiveComponent';
34 import { NsUpdateComponent } from 'NsUpdateComponent';
35 import { RestService } from 'RestService';
36 import { forkJoin, Observable } from 'rxjs';
37 import { ScalingComponent } from 'ScalingComponent';
38 import { SharedService } from 'SharedService';
39 import { ShowInfoComponent } from 'ShowInfoComponent';
40 import { StartStopRebuildComponent } from 'StartStopRebuildComponent';
41 import { VerticalScalingComponent } from 'VerticalScalingComponent';
42 import { VmMigrationComponent } from 'VmMigrationComponent';
43 import { DF, VDU, VNFD } from 'VNFDModel';
44 /**
45  * Creating component
46  * @Component takes NSInstancesActionComponent.html as template url
47  */
48 @Component({
49   templateUrl: './NSInstancesActionComponent.html',
50   styleUrls: ['./NSInstancesActionComponent.scss'],
51   changeDetection: ChangeDetectionStrategy.OnPush
52 })
53 /** Exporting a class @exports NSInstancesActionComponent */
54 export class NSInstancesActionComponent {
55   /** To get the value from the nspackage via valuePrepareFunction default Property of ng-smarttable @public */
56   public value: NSDInstanceData;
57
58   /** Invoke service injectors @public */
59   public injector: Injector;
60
61   /** Instance of the modal service @public */
62   public restService: RestService;
63
64   /** Config Status Check @public */
65   public configStatus: string;
66
67   /** Operational Status Check @public */
68   public operationalStatus: string;
69
70   /** CNF Status Check @public */
71   public k8sStatus: boolean = false;
72
73   /** get Admin Details @public */
74   public getAdminDetails: {};
75
76   /** Scaling is accepted @public */
77   public isScalingPresent: boolean = false;
78
79   /** Check the loading results for loader status @public */
80   public isLoadingNSInstanceAction: boolean = false;
81
82   /** Give the message for the loading @public */
83   public message: string = 'PLEASEWAIT';
84
85   /** Assign the VNF Details @public */
86   public vnfDetails: VNFD[] = [];
87
88   /** Contains instance ID @public */
89   public instanceID: string;
90
91   /** Contains operational dashboard view @public */
92   public isShowOperationalDashboard: boolean = false;
93
94   /** Instance of the modal service @private */
95   private modalService: NgbModal;
96
97   /** Holds teh instance of AuthService class of type AuthService @private */
98   private router: Router;
99
100   /** Contains all methods related to shared @private */
101   private sharedService: SharedService;
102
103   /** Notifier service to popup notification @private */
104   private notifierService: NotifierService;
105
106   /** Contains tranlsate instance @private */
107   private translateService: TranslateService;
108
109   /** Detect changes for the User Input */
110   private cd: ChangeDetectorRef;
111
112   /** Set timeout @private */
113   // eslint-disable-next-line @typescript-eslint/no-magic-numbers
114   private timeOut: number = 100;
115
116   constructor(injector: Injector) {
117     this.injector = injector;
118     this.modalService = this.injector.get(NgbModal);
119     this.restService = this.injector.get(RestService);
120     this.router = this.injector.get(Router);
121     this.sharedService = this.injector.get(SharedService);
122     this.notifierService = this.injector.get(NotifierService);
123     this.translateService = this.injector.get(TranslateService);
124     this.cd = this.injector.get(ChangeDetectorRef);
125   }
126
127   /**
128    * Lifecyle Hooks the trigger before component is instantiate
129    */
130   public ngOnInit(): void {
131     this.configStatus = this.value.ConfigStatus;
132     this.operationalStatus = this.value.OperationalStatus;
133     this.instanceID = this.value.identifier;
134     this.getAdminDetails = this.value.adminDetails;
135     for (const key of Object.keys(this.getAdminDetails)) {
136       if (key === 'deployed') {
137         // eslint-disable-next-line security/detect-object-injection
138         const adminData: {} = this.getAdminDetails[key];
139         for (const k8sData of Object.keys(adminData)) {
140           if (k8sData === 'K8s') {
141             // eslint-disable-next-line security/detect-object-injection
142             if (adminData[k8sData].length !== 0) {
143               this.k8sStatus = true;
144             }
145           }
146         }
147       }
148     }
149     this.isShowOperationalDashboard = !isNullOrUndefined(this.value.vcaStatus) ?
150       Object.keys(this.value.vcaStatus).length === 0 && typeof this.value.vcaStatus === 'object' : true;
151   }
152
153   /** Shows information using modalservice @public */
154   public infoNs(): void {
155     // eslint-disable-next-line security/detect-non-literal-fs-filename
156     this.modalService.open(ShowInfoComponent, { backdrop: 'static' }).componentInstance.params = {
157       id: this.instanceID,
158       page: 'ns-instance',
159       titleName: 'INSTANCEDETAILS'
160     };
161   }
162
163   /** Delete NS Instanace @public */
164   public deleteNSInstance(forceAction: boolean): void {
165     // eslint-disable-next-line security/detect-non-literal-fs-filename
166     const modalRef: NgbModalRef = this.modalService.open(DeleteComponent, { backdrop: 'static' });
167     modalRef.componentInstance.params = { forceDeleteType: forceAction };
168     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
169       if (result) {
170         this.sharedService.callData();
171       }
172     }).catch((): void => {
173       // Catch Navigation Error
174     });
175   }
176
177   /** History of operations for an Instanace @public */
178   public historyOfOperations(): void {
179     this.router.navigate(['/instances/ns/history-operations/', this.instanceID]).catch((): void => {
180       // Catch Navigation Error
181     });
182   }
183
184   /** NS Topology */
185   public nsTopology(): void {
186     this.router.navigate(['/instances/ns/', this.instanceID]).catch((): void => {
187       // Catch Navigation Error
188     });
189   }
190
191   /** Exec NS Primitive @public */
192   public execNSPrimitiveModal(): void {
193     // eslint-disable-next-line security/detect-non-literal-fs-filename
194     this.modalService.open(NSPrimitiveComponent, { backdrop: 'static' }).componentInstance.params = {
195       memberIndex: this.value.memberIndex,
196       nsConfig: this.value.nsConfig,
197       name: this.value.NsdName,
198       id: this.value.constituent
199     };
200   }
201
202   /** Redirect to Grafana Metrics @public */
203   public metrics(): void {
204     this.isLoadingNSInstanceAction = true;
205     this.restService.getResource(environment.NSDINSTANCES_URL + '/' + this.instanceID).subscribe((nsData: NSDDetails[]): void => {
206       nsData['vnfd-id'].forEach((vnfdID: string[]): void => {
207         this.restService.getResource(environment.VNFPACKAGES_URL + '/' + vnfdID)
208           .subscribe((vnfd: VNFD): void => {
209             vnfd.vdu.forEach((vduData: VDU): void => {
210               if (vduData['monitoring-parameter'] !== undefined && vduData['monitoring-parameter'].length > 0) {
211                 this.isLoadingNSInstanceAction = false;
212                 const location: string = environment.GRAFANA_URL + '/' + this.instanceID + '/osm-ns-metrics-metrics';
213                 // eslint-disable-next-line security/detect-non-literal-fs-filename
214                 window.open(location);
215               } else {
216                 this.isLoadingNSInstanceAction = false;
217                 this.notifierService.notify('error', this.translateService.instant('PAGE.NSMETRIC.METRICERROR'));
218               }
219             });
220             this.doChanges();
221           }, (error: ERRORDATA): void => {
222             this.restService.handleError(error, 'get');
223             this.isLoadingNSInstanceAction = false;
224           });
225       });
226     }, (error: ERRORDATA): void => {
227       this.restService.handleError(error, 'get');
228       this.isLoadingNSInstanceAction = false;
229     });
230   }
231
232   /**
233    * Do the manual scaling
234    * Here we are going to get a list of VNFD ID used in the instances
235    * and have this in array with URL created then pass to checkscaling method for forkjoin to get the data @public
236    */
237   public manualScaling(): void {
238     this.isLoadingNSInstanceAction = true;
239     const tempURL: Observable<{}>[] = [];
240     this.value.vnfID.forEach((id: string): void => {
241       const apiUrl: string = environment.VNFPACKAGESCONTENT_URL + '/' + id;
242       tempURL.push(this.restService.getResource(apiUrl));
243     });
244     this.checkScaling(tempURL);
245   }
246
247   /**
248    * Used to forkjoin to all the request to send parallely, get the data and check 'scaling-aspect' key is present @public
249    */
250   public checkScaling(URLS: Observable<{}>[]): void {
251     forkJoin(URLS).subscribe((data: VNFD[]): void => {
252       this.vnfDetails = data;
253       if (this.vnfDetails.length > 0) {
254         this.vnfDetails.forEach((vnfdData: VNFD): void => {
255           vnfdData.df.forEach((dfData: DF): void => {
256             if (!isNullOrUndefined(dfData['scaling-aspect']) && dfData['scaling-aspect'].length > 0) {
257               this.isScalingPresent = true;
258             }
259           });
260         });
261       }
262       this.isLoadingNSInstanceAction = false;
263       if (this.isScalingPresent) {
264         this.openScaling();
265       } else {
266         this.notifierService.notify('error', this.translateService.instant('SCALINGNOTFOUND'));
267       }
268       this.doChanges();
269     });
270   }
271
272   /** Open the scaling pop-up @public */
273   public openScaling(): void {
274     // eslint-disable-next-line security/detect-non-literal-fs-filename
275     const modalRef: NgbModalRef = this.modalService.open(ScalingComponent, { backdrop: 'static' });
276     modalRef.componentInstance.params = {
277       id: this.instanceID,
278       vnfID: this.value.vnfID,
279       nsID: this.value['nsd-id'],
280       nsd: this.value.nsd,
281       data: this.vnfDetails
282     };
283     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
284       if (result) {
285         this.sharedService.callData();
286       }
287     }).catch((): void => {
288       // Catch Navigation Error
289     });
290   }
291
292   /** To open VM Migration in NS Instances */
293   public openVmMigration(): void {
294     // eslint-disable-next-line security/detect-non-literal-fs-filename
295     const modalRef: NgbModalRef = this.modalService.open(VmMigrationComponent, { backdrop: 'static' });
296     modalRef.componentInstance.params = {
297       id: this.instanceID
298     };
299     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
300       if (result) {
301         this.sharedService.callData();
302       }
303     }).catch((): void => {
304       // Catch Navigation Error
305     });
306   }
307
308   /** To open the Ns Update pop-up */
309   public openNsUpdate(): void {
310     // eslint-disable-next-line security/detect-non-literal-fs-filename
311     const modalRef: NgbModalRef = this.modalService.open(NsUpdateComponent, { backdrop: 'static' });
312     modalRef.componentInstance.params = {
313       id: this.instanceID
314     };
315     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
316       if (result) {
317         this.sharedService.callData();
318       }
319     }).catch((): void => {
320       // Catch Navigation Error
321     });
322   }
323
324   /** To open the Start, Stop & Rebuild pop-up */
325   public openStart(actionType: string): void {
326     // eslint-disable-next-line security/detect-non-literal-fs-filename
327     const modalRef: NgbModalRef = this.modalService.open(StartStopRebuildComponent, { backdrop: 'static' });
328     modalRef.componentInstance.params = {
329       id: this.instanceID
330     };
331     if (actionType === 'start') {
332       modalRef.componentInstance.instanceTitle = this.translateService.instant('START');
333     } else if (actionType === 'stop') {
334       modalRef.componentInstance.instanceTitle = this.translateService.instant('STOP');
335     } else {
336       modalRef.componentInstance.instanceTitle = this.translateService.instant('REBUILD');
337     }
338     modalRef.componentInstance.instanceType = actionType;
339     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
340       if (result) {
341         this.sharedService.callData();
342       }
343     }).catch((): void => {
344       // Catch Navigation Error
345     });
346   }
347
348   /** To open the vertical Scaling pop-up */
349   public openVerticalScaling(): void {
350     // eslint-disable-next-line security/detect-non-literal-fs-filename
351     const modalRef: NgbModalRef = this.modalService.open(VerticalScalingComponent, { backdrop: 'static' });
352     modalRef.componentInstance.params = {
353       id: this.instanceID
354     };
355     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
356       if (result) {
357         this.sharedService.callData();
358       }
359     }).catch((): void => {
360       // Catch Navigation Error
361     });
362   }
363
364   /** Open the Healing pop-up @public */
365   public openHealing(): void {
366     // eslint-disable-next-line security/detect-non-literal-fs-filename
367     const modalRef: NgbModalRef = this.modalService.open(HealingComponent, { backdrop: 'static' });
368     modalRef.componentInstance.params = {
369       id: this.instanceID
370     };
371     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
372       if (result) {
373         this.sharedService.callData();
374       }
375     }).catch((): void => {
376       // Catch Navigation Error
377     });
378   }
379
380   /**
381    * Check any changes in the child component @public
382    */
383   public doChanges(): void {
384     setTimeout((): void => {
385       this.cd.detectChanges();
386     }, this.timeOut);
387   }
388 }