Fix Bug 2292: Invalid Member VNF index in Manual Scaling after NS Update remove operation
[osm/NG-UI.git] / src / app / utilities / ns-update / NsUpdateComponent.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: SANDHYA JS (sandhya.j@tataelxsi.co.in)
17 */
18 /**
19  * @file Ns Update Component
20  */
21 import { isNullOrUndefined } from 'util';
22 import { HttpHeaders } from '@angular/common/http';
23 import { Component, Injector, Input, OnInit } from '@angular/core';
24 import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
25 import { Router } from '@angular/router';
26 import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
27 import { TranslateService } from '@ngx-translate/core';
28 import { APIURLHEADER, CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
29 import { environment } from 'environment';
30 import { NSUPDATE, TERMINATEVNF } from 'NSInstanceModel';
31 import { RestService } from 'RestService';
32 import { SharedService } from 'SharedService';
33 import { VNFD } from 'VNFDModel';
34 import { InstanceData, VNFInstanceDetails } from 'VNFInstanceModel';
35 import { WarningComponent } from 'WarningComponent';
36
37 /**
38  * Creating component
39  * @Component takes NsUpdateComponent.html as template url
40  */
41 @Component({
42     selector: 'app-ns-update',
43     templateUrl: './NsUpdateComponent.html',
44     styleUrls: ['./NsUpdateComponent.scss']
45 })
46 export class NsUpdateComponent implements OnInit {
47     /** To inject services @public */
48     public injector: Injector;
49     /** Instance for active modal service @public */
50     public activeModal: NgbActiveModal;
51     /** Check the loading results @public */
52     public isLoadingResults: Boolean = false;
53     /** Give the message for the loading @public */
54     public message: string = 'PLEASEWAIT';
55     /** FormGroup instance added to the form @ html @public */
56     public nsUpdateForm: FormGroup;
57     /** Items for the member types @public */
58     public memberTypes: {}[];
59     /** Contains objects that is used to hold types of primitive @public */
60     public updateTypeList: {}[] = [];
61     /** Form valid on submit trigger @public */
62     public submitted: boolean = false;
63     /** Give the update type @public */
64     public terminateVnf: string;
65     /** Model value used to hold selected MemberVNFIndex @public */
66     public memberIndexValue: string;
67     /** Form Check vnfdId Section @public */
68     public vnfdIdShow: boolean = false;
69     /** Contains MemberVNFIndex values @public */
70     public memberVnfIndex: {}[] = [];
71     /** Contains MemberVNFIndex content @public */
72     public selectedVnf: {}[];
73     /** Array holds VNFR Data filtered with nsr ID @public */
74     public nsIdFilteredData: {}[] = [];
75     /** Contains vnfdId value @public */
76     public vnfdId: string;
77     /** Contains vnfId value of the selected MemberVnfIndex @public */
78     public vnfID: string;
79     /** Contains version of the selected MemberVnfIndex @public */
80     public version: string;
81     /** Contains version of the vnfId @public */
82     public vnfversion: string;
83     /** Contains vnfInstanceId of the selected MemberVnfIndex  @public */
84     public instanceId: string;
85     /** Selected VNFInstanceId @public */
86     public selectedvnfId: string = '';
87     /** Input contains component objects @private */
88     @Input() private params: URLPARAMS;
89     /** FormBuilder instance added to the formBuilder @private */
90     private formBuilder: FormBuilder;
91     /** Contains tranlsate instance @private */
92     private translateService: TranslateService;
93     /** Instance of the rest service @private */
94     private restService: RestService;
95     /** Controls the header form @private */
96     private headers: HttpHeaders;
97     /** Contains all methods related to shared @private */
98     private sharedService: SharedService;
99     /** Holds the instance of AuthService class of type AuthService @private */
100     private router: Router;
101     /** Instance of the modal service @private */
102     private modalService: NgbModal;
103     constructor(injector: Injector) {
104         this.injector = injector;
105         this.restService = this.injector.get(RestService);
106         this.activeModal = this.injector.get(NgbActiveModal);
107         this.formBuilder = this.injector.get(FormBuilder);
108         this.sharedService = this.injector.get(SharedService);
109         this.translateService = this.injector.get(TranslateService);
110         this.router = this.injector.get(Router);
111         this.modalService = this.injector.get(NgbModal);
112         this.updateTypeList = [
113             {
114                 title: this.translateService.instant('VNFPKGCHANGE'),
115                 value: 'CHANGE_VNFPKG'
116             },
117             {
118                 title: this.translateService.instant('REMOVEVNF'),
119                 value: 'REMOVE_VNF'
120             }
121         ];
122     }
123     /** convenience getter for easy access to form fields */
124     get f(): FormGroup['controls'] { return this.nsUpdateForm.controls; }
125     /**
126      * Lifecyle Hooks the trigger before component is instantiate
127      */
128     public ngOnInit(): void {
129         this.initializeForm();
130         this.getMemberVnfIndex();
131         this.headers = new HttpHeaders({
132             'Content-Type': 'application/json',
133             Accept: 'application/json',
134             'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
135         });
136     }
137
138     /** Initialize Ns Update Forms @public */
139     public initializeForm(): void {
140         this.nsUpdateForm = this.formBuilder.group({
141             updateType: [null, [Validators.required]],
142             memberVnfIndex: [null, [Validators.required]],
143             vnfdId: [null, [Validators.required]]
144         });
145     }
146
147     /** Getting MemberVnfIndex using NSDescriptor API @public */
148     public getMemberVnfIndex(): void {
149         this.isLoadingResults = true;
150         const vnfInstanceData: {}[] = [];
151         this.restService.getResource(environment.VNFINSTANCES_URL).subscribe((vnfInstancesData: VNFInstanceDetails[]): void => {
152             vnfInstancesData.forEach((vnfData: VNFInstanceDetails): void => {
153                 const vnfdRef: string = 'vnfd-ref';
154                 const memberIndex: string = 'member-vnf-index-ref';
155                 const nsrId: string = 'nsr-id-ref';
156                 const vnfId: string = 'vnfd-id';
157                 const vnfDataObj: {} =
158                 {
159                     // eslint-disable-next-line security/detect-object-injection
160                     VNFD: vnfData[vnfdRef],
161                     VNFInstanceId: vnfData._id,
162                     // eslint-disable-next-line security/detect-object-injection
163                     MemberIndex: vnfData[memberIndex],
164                     // eslint-disable-next-line security/detect-object-injection
165                     NS: vnfData[nsrId],
166                     // eslint-disable-next-line security/detect-object-injection
167                     VNFID: vnfData[vnfId]
168                 };
169                 vnfInstanceData.push(vnfDataObj);
170             });
171             const nsId: string = 'NS';
172             // eslint-disable-next-line security/detect-object-injection
173             this.nsIdFilteredData = vnfInstanceData.filter((vnfdData: {}[]): boolean => vnfdData[nsId] === this.params.id);
174             this.nsIdFilteredData.forEach((resVNF: InstanceData): void => {
175                 const assignMemberIndex: {} = {
176                     id: resVNF.MemberIndex,
177                     vnfinstanceId: resVNF.VNFInstanceId
178                 };
179                 this.memberVnfIndex.push(assignMemberIndex);
180             });
181             this.memberTypes = this.memberVnfIndex;
182             this.isLoadingResults = false;
183         }, (error: ERRORDATA): void => {
184             this.restService.handleError(error, 'get');
185             this.isLoadingResults = false;
186         });
187     }
188
189     /**
190      *  Fetching the VNFR Information filtered with MemberVnfIndex
191      *  Get the selected VNF Instance ID
192      */
193     public getSelectedVNF(id: string): void {
194         this.instanceId = id;
195         let memberIndexFilteredData: {}[] = [];
196         const memberIndex: string = 'MemberIndex';
197         memberIndexFilteredData = this.nsIdFilteredData.filter((vnfdData: {}[]): boolean =>
198             // eslint-disable-next-line security/detect-object-injection
199             vnfdData[memberIndex] === this.memberIndexValue);
200         const vnfId: string = 'VNFID';
201         const selectedvnfId: string = 'VNFD';
202         this.selectedVnf = memberIndexFilteredData;
203         for (const data of memberIndexFilteredData) {
204             // eslint-disable-next-line security/detect-object-injection
205             this.vnfID = data[vnfId];
206             // eslint-disable-next-line security/detect-object-injection
207             this.selectedvnfId = data[selectedvnfId];
208         }
209     }
210
211     /** Trigger NsUpdate on submit */
212     public triggerNsUpdate(): void {
213         this.submitted = true;
214         this.sharedService.cleanForm(this.nsUpdateForm);
215         if (this.nsUpdateForm.invalid) { return; } // Proceed, onces form is valid
216         this.vnfdId = this.nsUpdateForm.value.vnfdId;
217         this.checkUpdateType();
218     }
219
220     /** Ns Update on submit */
221     public onSubmit(): void {
222         if (this.terminateVnf === 'REMOVE_VNF') {
223             const nsUpdateTerminatePayload: TERMINATEVNF = {
224                 lcmOperationType: 'update',
225                 updateType: this.nsUpdateForm.value.updateType,
226                 nsInstanceId: this.params.id,
227                 removeVnfInstanceId: this.instanceId
228             };
229             this.nsUpdateInitialization(nsUpdateTerminatePayload);
230         } else {
231             const nsUpdatePayload: NSUPDATE = {
232                 lcmOperationType: 'update',
233                 updateType: this.nsUpdateForm.value.updateType,
234                 nsInstanceId: this.params.id,
235                 changeVnfPackageData: {
236                     vnfInstanceId: this.instanceId,
237                     vnfdId: this.nsUpdateForm.value.vnfdId
238                 }
239             };
240             this.nsUpdateInitialization(nsUpdatePayload);
241         }
242     }
243
244     /**
245      *  Open Modal based on selected NS-UPDATE Type
246      */
247     public checkUpdateType(): void {
248         this.isLoadingResults = true;
249         if (this.nsUpdateForm.value.updateType === 'CHANGE_VNFPKG') {
250             this.checkVersion();
251         } else {
252             // eslint-disable-next-line security/detect-non-literal-fs-filename
253             const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
254             modalRef.componentInstance.heading = this.translateService.instant('TERMINATEVNF');
255             modalRef.componentInstance.confirmationMessage = this.translateService.instant('TERMINATEVNFCONTENT');
256             modalRef.componentInstance.submitMessage = this.translateService.instant('TERMINATEVNF');
257             modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
258                 if (result.message === CONFIGCONSTANT.done) {
259                     this.onSubmit();
260                 }
261             }).catch((): void => {
262                 // Catch Navigation Error
263             });
264         }
265         this.isLoadingResults = false;
266     }
267
268     /** To check the versions are matching or not for 'CHANGE_VNFPKG' type */
269     public checkVersion(): void {
270         this.isLoadingResults = true;
271         const vnfDetails: {}[] = [];
272         this.restService.getResource(environment.VNFPACKAGESCONTENT_URL + '/' + this.vnfdId).subscribe((vnfData: VNFD[]): void => {
273             if (!isNullOrUndefined(vnfData['software-version'])) {
274                 this.version = vnfData['software-version'];
275             }
276             this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfDetail: VNFD[]): void => {
277                 vnfDetail.forEach((vnfDatas: VNFD): void => {
278                     const vnfDataObj: {} =
279                     {
280                         VNFID: vnfDatas._id,
281                         version: vnfDatas['software-version']
282                     };
283                     vnfDetails.push(vnfDataObj);
284                 });
285                 let vnfIdFilteredData: {}[] = [];
286                 const vnfID: string = 'VNFID';
287                 const version: string = 'version';
288                 // eslint-disable-next-line security/detect-object-injection
289                 vnfIdFilteredData = vnfDetails.filter((vnfdData: {}[]): boolean => vnfdData[vnfID] === this.vnfID);
290                 for (const data of vnfIdFilteredData) {
291                     // eslint-disable-next-line security/detect-object-injection
292                     this.vnfversion = data[version];
293                 }
294                 if (this.version === this.vnfversion) {
295                     // eslint-disable-next-line security/detect-non-literal-fs-filename
296                     const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
297                     modalRef.componentInstance.heading = this.translateService.instant('UPDATENS');
298                     modalRef.componentInstance.confirmationMessage = this.translateService.instant('GENERICCONTENT');
299                     modalRef.componentInstance.submitMessage = this.translateService.instant('UPDATENS');
300                     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
301                         if (result.message === CONFIGCONSTANT.done) {
302                             this.onSubmit();
303                         }
304                     }).catch((): void => { //empty
305                     }
306                     );
307                 } else {
308                     // eslint-disable-next-line security/detect-non-literal-fs-filename
309                     const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
310                     modalRef.componentInstance.heading = this.translateService.instant('REDEPLOY');
311                     modalRef.componentInstance.confirmationMessage = this.translateService.instant('REDEPLOYCONTENT');
312                     modalRef.componentInstance.submitMessage = this.translateService.instant('REDEPLOY');
313                     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
314                         if (result.message === CONFIGCONSTANT.done) {
315                             this.onSubmit();
316                         }
317                     }).catch((): void => { //empty
318                     });
319                 }
320             }, (error: ERRORDATA): void => {
321                 this.restService.handleError(error, 'get');
322                 this.isLoadingResults = false;
323             });
324             this.isLoadingResults = false;
325         }, (error: ERRORDATA): void => {
326             this.restService.handleError(error, 'get');
327             this.isLoadingResults = false;
328         });
329     }
330
331     /** Initialize the Ns Update @public */
332     public nsUpdateInitialization(nsUpdatePayload: object): void {
333         this.isLoadingResults = true;
334         const apiURLHeader: APIURLHEADER = {
335             url: environment.NSDINSTANCES_URL + '/' + this.params.id + '/update',
336             httpOptions: { headers: this.headers }
337         };
338         const modalData: MODALCLOSERESPONSEDATA = {
339             message: 'Done'
340         };
341         this.restService.postResource(apiURLHeader, nsUpdatePayload).subscribe((result: {}): void => {
342             this.activeModal.close(modalData);
343             this.router.navigate(['/instances/ns/history-operations/' + this.params.id]).catch((): void => {
344                 // Catch Navigation Error
345             });
346         }, (error: ERRORDATA): void => {
347             this.restService.handleError(error, 'post');
348             this.isLoadingResults = false;
349         });
350     }
351
352     /** To enable or disable vnfdId field @public */
353     public terminateVNF(value: string): void {
354         this.terminateVnf = value;
355         if (this.terminateVnf === 'REMOVE_VNF') {
356             this.vnfdIdShow = true;
357             this.getFormControl('vnfdId').disable();
358         } else {
359             this.vnfdIdShow = false;
360             this.getFormControl('vnfdId').enable();
361         }
362     }
363
364     /** Used to get the AbstractControl of controlName passed @private */
365     private getFormControl(controlName: string): AbstractControl {
366         // eslint-disable-next-line security/detect-object-injection
367         return this.nsUpdateForm.controls[controlName];
368     }
369 }