Feature 11038: Enhancement of Vertical Scale Feature and merge in update API
[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 { HttpHeaders } from '@angular/common/http';
22 import { Component, Injector, Input, OnInit } from '@angular/core';
23 import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
24 import { Router } from '@angular/router';
25 import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
26 import { TranslateService } from '@ngx-translate/core';
27 import { APIURLHEADER, CONFIGCONSTANT, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
28 import { environment } from 'environment';
29 import { NSUPDATE, TERMINATEVNF } from 'NSInstanceModel';
30 import { RestService } from 'RestService';
31 import { isNullOrUndefined } from 'SharedService';
32 import { SharedService } from 'SharedService';
33 import { VNFD } from 'VNFDModel';
34 import { InstanceData, VDUDETAIL, VDUR, 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     /** Form Check vduId Section @public */
70     public vduIdShow: boolean = false;
71     /** Contains MemberVNFIndex values @public */
72     public memberVnfIndex: {}[] = [];
73     /** Contains MemberVNFIndex content @public */
74     public selectedVnf: {}[];
75     /** Array holds VNFR Data filtered with nsr ID @public */
76     public nsIdFilteredData: {}[] = [];
77     /** Contains vnfdId value @public */
78     public vnfdId: string;
79     /** Contains vnfId value of the selected MemberVnfIndex @public */
80     public vnfID: string;
81     /** Contains version of the selected MemberVnfIndex @public */
82     public version: string;
83     /** Contains version of the vnfId @public */
84     public vnfversion: string;
85     /** Contains vnfInstanceId of the selected MemberVnfIndex  @public */
86     public instanceId: string;
87     /** Selected VNFInstanceId @public */
88     public selectedvnfId: string = '';
89     /** Items for vduId & countIndex @public */
90     public vdu: {}[];
91     /** Contains vduId @public */
92     public vduId: {};
93     /** Input contains component objects @private */
94     @Input() private params: URLPARAMS;
95     /** FormBuilder instance added to the formBuilder @private */
96     private formBuilder: FormBuilder;
97     /** Contains tranlsate instance @private */
98     private translateService: TranslateService;
99     /** Instance of the rest service @private */
100     private restService: RestService;
101     /** Controls the header form @private */
102     private headers: HttpHeaders;
103     /** Contains all methods related to shared @private */
104     private sharedService: SharedService;
105     /** Holds the instance of AuthService class of type AuthService @private */
106     private router: Router;
107     /** Instance of the modal service @private */
108     private modalService: NgbModal;
109     constructor(injector: Injector) {
110         this.injector = injector;
111         this.restService = this.injector.get(RestService);
112         this.activeModal = this.injector.get(NgbActiveModal);
113         this.formBuilder = this.injector.get(FormBuilder);
114         this.sharedService = this.injector.get(SharedService);
115         this.translateService = this.injector.get(TranslateService);
116         this.router = this.injector.get(Router);
117         this.modalService = this.injector.get(NgbModal);
118         this.updateTypeList = [
119             {
120                 title: this.translateService.instant('VNFPKGCHANGE'),
121                 value: 'CHANGE_VNFPKG'
122             },
123             {
124                 title: this.translateService.instant('REMOVEVNF'),
125                 value: 'REMOVE_VNF'
126             },
127             {
128                 title: this.translateService.instant('VERTICALSCALE'),
129                 value: 'VERTICAL_SCALE'
130             }
131         ];
132     }
133     /** convenience getter for easy access to form fields */
134     get f(): FormGroup['controls'] { return this.nsUpdateForm.controls; }
135     /**
136      * Lifecyle Hooks the trigger before component is instantiate
137      */
138     public ngOnInit(): void {
139         this.initializeForm();
140         this.getMemberVnfIndex();
141         this.headers = new HttpHeaders({
142             'Content-Type': 'application/json',
143             Accept: 'application/json',
144             'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
145         });
146     }
147
148     /** Initialize Ns Update Forms @public */
149     public initializeForm(): void {
150         this.nsUpdateForm = this.formBuilder.group({
151             updateType: [null, [Validators.required]],
152             memberVnfIndex: [null, [Validators.required]],
153             vnfdId: [null, [Validators.required]],
154             vduId: [null, [Validators.required]],
155             countIndex: [null, [Validators.required]]
156         });
157     }
158
159     /** Getting MemberVnfIndex using NSDescriptor API @public */
160     public getMemberVnfIndex(): void {
161         this.isLoadingResults = true;
162         const vnfInstanceData: {}[] = [];
163         this.restService.getResource(environment.VNFINSTANCES_URL).subscribe((vnfInstancesData: VNFInstanceDetails[]): void => {
164             vnfInstancesData.forEach((vnfData: VNFInstanceDetails): void => {
165                 const vnfdRef: string = 'vnfd-ref';
166                 const memberIndex: string = 'member-vnf-index-ref';
167                 const nsrId: string = 'nsr-id-ref';
168                 const vnfId: string = 'vnfd-id';
169                 const vnfDataObj: {} =
170                 {
171                     // eslint-disable-next-line security/detect-object-injection
172                     VNFD: vnfData[vnfdRef],
173                     VNFInstanceId: vnfData._id,
174                     // eslint-disable-next-line security/detect-object-injection
175                     MemberIndex: vnfData[memberIndex],
176                     // eslint-disable-next-line security/detect-object-injection
177                     NS: vnfData[nsrId],
178                     // eslint-disable-next-line security/detect-object-injection
179                     VNFID: vnfData[vnfId]
180                 };
181                 vnfInstanceData.push(vnfDataObj);
182             });
183             const nsId: string = 'NS';
184             // eslint-disable-next-line security/detect-object-injection
185             this.nsIdFilteredData = vnfInstanceData.filter((vnfdData: {}[]): boolean => vnfdData[nsId] === this.params.id);
186             this.nsIdFilteredData.forEach((resVNF: InstanceData): void => {
187                 const assignMemberIndex: {} = {
188                     id: resVNF.MemberIndex,
189                     vnfinstanceId: resVNF.VNFInstanceId
190                 };
191                 this.memberVnfIndex.push(assignMemberIndex);
192             });
193             this.memberTypes = this.memberVnfIndex;
194             this.isLoadingResults = false;
195         }, (error: ERRORDATA): void => {
196             this.restService.handleError(error, 'get');
197             this.isLoadingResults = false;
198         });
199     }
200
201     /**
202      *  Fetching the VNFR Information filtered with MemberVnfIndex
203      *  Get the selected VNF Instance ID
204      */
205     public getSelectedVNF(id: string): void {
206         this.instanceId = id;
207         this.getVdu(this.instanceId);
208         let memberIndexFilteredData: {}[] = [];
209         const memberIndex: string = 'MemberIndex';
210         memberIndexFilteredData = this.nsIdFilteredData.filter((vnfdData: {}[]): boolean =>
211             // eslint-disable-next-line security/detect-object-injection
212             vnfdData[memberIndex] === this.memberIndexValue);
213         const vnfId: string = 'VNFID';
214         const selectedvnfId: string = 'VNFD';
215         this.selectedVnf = memberIndexFilteredData;
216         for (const data of memberIndexFilteredData) {
217             // eslint-disable-next-line security/detect-object-injection
218             this.vnfID = data[vnfId];
219             // eslint-disable-next-line security/detect-object-injection
220             this.selectedvnfId = data[selectedvnfId];
221         }
222     }
223
224     /** Getting vdu-id & count-index from API */
225     public getVdu(id: string): void {
226         const vnfInstanceData: {}[] = [];
227         this.getFormControl('vduId').setValue(null);
228         this.getFormControl('countIndex').setValue(null);
229         if (!isNullOrUndefined(id)) {
230             this.restService.getResource(environment.VNFINSTANCES_URL + '/' + id).
231                 subscribe((vnfInstanceDetail: VNFInstanceDetails): void => {
232                     this.instanceId = id;
233                     this.selectedvnfId = vnfInstanceDetail['vnfd-ref'];
234                     if (!isNullOrUndefined(vnfInstanceDetail.vdur)) {
235                         vnfInstanceDetail.vdur.forEach((vdu: VDUR): void => {
236                             const vnfInstanceDataObj: {} =
237                             {
238                                 'count-index': vdu['count-index'],
239                                 VDU: vdu['vdu-id-ref']
240
241                             };
242                             vnfInstanceData.push(vnfInstanceDataObj);
243                         });
244                         this.vdu = vnfInstanceData;
245                         this.vduId = this.vdu.filter((vdu: VDUDETAIL, index: number, self: {}[]): {} =>
246                             index === self.findIndex((t: VDUDETAIL): {} => (
247                                 t.VDU === vdu.VDU
248                             ))
249                         );
250                     }
251                 }, (error: ERRORDATA): void => {
252                     this.restService.handleError(error, 'get');
253                     this.isLoadingResults = false;
254                 });
255         }
256     }
257
258     /** Trigger NsUpdate on submit */
259     public triggerNsUpdate(): void {
260         this.submitted = true;
261         this.sharedService.cleanForm(this.nsUpdateForm);
262         if (this.nsUpdateForm.invalid) { return; } // Proceed, onces form is valid
263         this.vnfdId = this.nsUpdateForm.value.vnfdId;
264         if (this.terminateVnf === 'VERTICAL_SCALE') {
265             this.getFormControl('countIndex').enable();
266             this.onSubmit();
267         } else {
268             this.checkUpdateType();
269         }
270     }
271
272     /** Ns Update on submit */
273     public onSubmit(): void {
274         if (this.terminateVnf === 'REMOVE_VNF') {
275             const nsUpdateTerminatePayload: TERMINATEVNF = {
276                 lcmOperationType: 'update',
277                 updateType: this.nsUpdateForm.value.updateType,
278                 nsInstanceId: this.params.id,
279                 removeVnfInstanceId: this.instanceId
280             };
281             this.nsUpdateInitialization(nsUpdateTerminatePayload);
282         } else if (this.terminateVnf === 'CHANGE_VNFPKG') {
283             const nsUpdatePayload: NSUPDATE = {
284                 lcmOperationType: 'update',
285                 updateType: this.nsUpdateForm.value.updateType,
286                 nsInstanceId: this.params.id,
287                 changeVnfPackageData: {
288                     vnfInstanceId: this.instanceId,
289                     vnfdId: this.nsUpdateForm.value.vnfdId
290                 }
291             };
292             this.nsUpdateInitialization(nsUpdatePayload);
293         } else if (this.terminateVnf === 'VERTICAL_SCALE') {
294             const nsUpdatePayload: NSUPDATE = {
295                 lcmOperationType: 'update',
296                 updateType: this.nsUpdateForm.value.updateType,
297                 nsInstanceId: this.params.id,
298                 verticalScaleVnf: {
299                     vnfInstanceId: this.instanceId,
300                     vnfdId: this.nsUpdateForm.value.vnfdId,
301                     countIndex: 0,
302                     vduId: this.nsUpdateForm.value.vduId
303                 }
304             };
305             this.nsUpdateInitialization(nsUpdatePayload);
306         }
307     }
308
309     /**
310      *  Open Modal based on selected NS-UPDATE Type
311      */
312     public checkUpdateType(): void {
313         this.isLoadingResults = true;
314         if (this.nsUpdateForm.value.updateType === 'CHANGE_VNFPKG') {
315             this.checkVersion();
316         } else if (this.nsUpdateForm.value.updateType === 'REMOVE_VNF') {
317             // eslint-disable-next-line security/detect-non-literal-fs-filename
318             const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
319             modalRef.componentInstance.heading = this.translateService.instant('TERMINATEVNF');
320             modalRef.componentInstance.confirmationMessage = this.translateService.instant('TERMINATEVNFCONTENT');
321             modalRef.componentInstance.submitMessage = this.translateService.instant('TERMINATEVNF');
322             modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
323                 if (result.message === CONFIGCONSTANT.done) {
324                     this.onSubmit();
325                 }
326             }).catch((): void => {
327                 // Catch Navigation Error
328             });
329         }
330         this.isLoadingResults = false;
331     }
332
333     /** To check the versions are matching or not for 'CHANGE_VNFPKG' type */
334     public checkVersion(): void {
335         this.isLoadingResults = true;
336         const vnfDetails: {}[] = [];
337         this.restService.getResource(environment.VNFPACKAGESCONTENT_URL + '/' + this.vnfdId).subscribe((vnfData: VNFD[]): void => {
338             if (!isNullOrUndefined(vnfData['software-version'])) {
339                 this.version = vnfData['software-version'];
340             }
341             this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfDetail: VNFD[]): void => {
342                 vnfDetail.forEach((vnfDatas: VNFD): void => {
343                     const vnfDataObj: {} =
344                     {
345                         VNFID: vnfDatas._id,
346                         version: vnfDatas['software-version']
347                     };
348                     vnfDetails.push(vnfDataObj);
349                 });
350                 let vnfIdFilteredData: {}[] = [];
351                 const vnfID: string = 'VNFID';
352                 const version: string = 'version';
353                 // eslint-disable-next-line security/detect-object-injection
354                 vnfIdFilteredData = vnfDetails.filter((vnfdData: {}[]): boolean => vnfdData[vnfID] === this.vnfID);
355                 for (const data of vnfIdFilteredData) {
356                     // eslint-disable-next-line security/detect-object-injection
357                     this.vnfversion = data[version];
358                 }
359                 if (this.version === this.vnfversion) {
360                     // eslint-disable-next-line security/detect-non-literal-fs-filename
361                     const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
362                     modalRef.componentInstance.heading = this.translateService.instant('UPDATENS');
363                     modalRef.componentInstance.confirmationMessage = this.translateService.instant('GENERICCONTENT');
364                     modalRef.componentInstance.submitMessage = this.translateService.instant('UPDATENS');
365                     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
366                         if (result.message === CONFIGCONSTANT.done) {
367                             this.onSubmit();
368                         }
369                     }).catch((): void => { //empty
370                     }
371                     );
372                 } else {
373                     // eslint-disable-next-line security/detect-non-literal-fs-filename
374                     const modalRef: NgbModalRef = this.modalService.open(WarningComponent, { backdrop: 'static' });
375                     modalRef.componentInstance.heading = this.translateService.instant('REDEPLOY');
376                     modalRef.componentInstance.confirmationMessage = this.translateService.instant('REDEPLOYCONTENT');
377                     modalRef.componentInstance.submitMessage = this.translateService.instant('REDEPLOY');
378                     modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
379                         if (result.message === CONFIGCONSTANT.done) {
380                             this.onSubmit();
381                         }
382                     }).catch((): void => { //empty
383                     });
384                 }
385             }, (error: ERRORDATA): void => {
386                 this.restService.handleError(error, 'get');
387                 this.isLoadingResults = false;
388             });
389             this.isLoadingResults = false;
390         }, (error: ERRORDATA): void => {
391             this.restService.handleError(error, 'get');
392             this.isLoadingResults = false;
393         });
394     }
395
396     /** Initialize the Ns Update @public */
397     public nsUpdateInitialization(nsUpdatePayload: object): void {
398         this.isLoadingResults = true;
399         const apiURLHeader: APIURLHEADER = {
400             url: environment.NSDINSTANCES_URL + '/' + this.params.id + '/update',
401             httpOptions: { headers: this.headers }
402         };
403         const modalData: MODALCLOSERESPONSEDATA = {
404             message: 'Done'
405         };
406         this.restService.postResource(apiURLHeader, nsUpdatePayload).subscribe((result: {}): void => {
407             this.activeModal.close(modalData);
408             this.router.navigate(['/instances/ns/history-operations/' + this.params.id]).catch((): void => {
409                 // Catch Navigation Error
410             });
411         }, (error: ERRORDATA): void => {
412             this.restService.handleError(error, 'post');
413             this.isLoadingResults = false;
414         });
415     }
416
417     /** To enable or disable vnfdId field @public */
418     public terminateVNF(value: string): void {
419         this.terminateVnf = value;
420         if (this.terminateVnf === 'REMOVE_VNF') {
421             this.vnfdIdShow = true;
422             this.vduIdShow = false;
423             this.getFormControl('vnfdId').disable();
424             this.getFormControl('vduId').disable();
425             this.getFormControl('countIndex').disable();
426         } else if (this.terminateVnf === 'CHANGE_VNFPKG') {
427             this.vnfdIdShow = false;
428             this.vduIdShow = false;
429             this.getFormControl('vnfdId').enable();
430             this.getFormControl('vduId').disable();
431             this.getFormControl('countIndex').disable();
432         } else if (this.terminateVnf === 'VERTICAL_SCALE') {
433             this.vnfdIdShow = false;
434             this.vduIdShow = true;
435             this.getFormControl('vnfdId').enable();
436             this.getFormControl('vduId').enable();
437             this.getFormControl('countIndex').disable();
438         }
439     }
440
441     /** Getting count-index by filtering id  */
442     public getCountIndex(): void {
443         this.getFormControl('countIndex').patchValue('0');
444     }
445
446     /** Used to get the AbstractControl of controlName passed @private */
447     private getFormControl(controlName: string): AbstractControl {
448         // eslint-disable-next-line security/detect-object-injection
449         return this.nsUpdateForm.controls[controlName];
450     }
451 }