added ansible server functionality
[appc/cdt.git] / src / app / test / test.component.ts
1 /*
2 ============LICENSE_START==========================================
3 ===================================================================
4 Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
5 ===================================================================
6 Copyright (C) 2018 IBM.
7 ===================================================================
8 Unless otherwise specified, all software contained herein is licensed
9 under the Apache License, Version 2.0 (the License);
10 you may not use this software except in compliance with the License.
11 You may obtain a copy of the License at
12
13     http://www.apache.org/licenses/LICENSE-2.0
14
15 Unless required by applicable law or agreed to in writing, software
16 distributed under the License is distributed on an "AS IS" BASIS,
17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 See the License for the specific language governing permissions and
19 limitations under the License.
20 ============LICENSE_END============================================
21 */
22
23 import { Component, OnInit } from '@angular/core';
24 import { NgxSpinnerService } from 'ngx-spinner';
25 import { saveAs } from 'file-saver';
26 import { Location } from '@angular/common';
27 import { ActivatedRoute, Router } from '@angular/router';
28 import { NotificationService } from '.././shared/services/notification.service';
29 import { ParamShareService } from '.././shared/services/paramShare.service';
30 import { MappingEditorService } from '.././shared/services/mapping-editor.service';
31 import { NotificationsService } from 'angular2-notifications';
32 import { HttpUtilService } from '.././shared/services/httpUtil/http-util.service';
33 import 'rxjs/add/observable/interval';
34 import { Observable } from 'rxjs/Observable';
35 import { environment } from '../.././environments/environment';
36 import { UtilityService } from '.././shared/services/utilityService/utility.service';
37 import 'rxjs/add/operator/map';
38 import * as XLSX from 'xlsx';
39 import { NgProgress } from 'ngx-progressbar';
40
41
42 let YAML = require('yamljs');
43
44 type AOA = Array<Array<any>>;
45 declare var $: any;
46
47 @Component({ selector: 'test', templateUrl: './test.component.html', styleUrls: ['./test.component.css'] })
48 export class TestComponent implements OnInit {
49     public displayParamObjects;
50     options = {
51         timeOut: 1000,
52         showProgressBar: true,
53         pauseOnHover: true,
54         clickToClose: true,
55         maxLength: 200
56     };
57     public action: any;
58     public vnfId: any;
59     public item: any = {};
60
61     public vnfType: any;
62     vnfcType: any;
63     protocol: any;
64     mode: any = 'NORMAL';
65     public force = 'TRUE';
66     ttl: any;
67     public formattedNameValuePairs = {};
68     public requestId = '';
69     public enableBrowse: boolean = true;
70     public enableSpinner: boolean = false;
71     host: any;
72     public refNameObj = {};
73
74     public artifactName;
75     public type;
76     public transactions = '';
77     public uploadFileName;
78
79     public payload = {};
80     public lastvmJson = {};
81     public vmPayload = [];
82     public subPayload = {};
83     public vmJson = {};
84     public vnfcJson = {};
85     public flag = 1;
86     public oldListName1 = '';
87     public actionIdentifiers = {};
88     public apiRequest = '';
89     public apiResponse = '';
90     public statusResponse;
91     public appcTimestampResponse;
92     public outputTimeStamp;
93     public status;
94     public statusReason;
95     public errorResponse;
96     public timer;
97     public subscribe;
98     public enableTestButton: boolean = false;
99     public enableAbort: boolean = false;
100     public showStatusResponseDiv: boolean = false;
101     public enablePollButton: boolean = true;
102     public pollCounter = 0;
103     public enableCounterDiv: boolean = false;
104     public enableDownload: boolean = false;
105     private userId = localStorage['userId'];
106     timeStampInt: number;
107     AppcTimeStampInt: number;
108     AppcTimeDiff: number;
109     isAppcTimestampReceived: boolean = false;
110
111     constructor (private location: Location, private activeRoutes: ActivatedRoute, private notificationService: NotificationService, private nService: NotificationsService, private router: Router, private paramShareService: ParamShareService, private mappingEditorService: MappingEditorService, private httpUtil: HttpUtilService,
112         private utiltiy: UtilityService, private ngProgress: NgProgress, private spinner: NgxSpinnerService) {
113
114     }
115
116     ngOnInit() {
117         let timeStampI = new Date();
118         console.log("ngOnInit: local timeStamp:[" + timeStampI + "]");
119         let timeStampS = timeStampI.toISOString();
120         console.log("ngOnInit: local ISO timestamp:[" + timeStampS + "]");
121         //.. send HTTP request to APPC
122         this.getAppcTimestamp();
123     }
124
125
126     /*public download() {
127       let stringData: any;
128       stringData = JSON.stringify(this.paramShareService.getSessionParamData());
129       let paramsKeyValueFromEditor: JSON;
130       paramsKeyValueFromEditor = JSON.parse(stringData);
131       let fileName = 'param_' + this.action + '_' + this.type + '_' + "0.0.1" + 'V';
132       this.JSONToCSVConvertor([paramsKeyValueFromEditor], fileName, true);
133
134     }*/
135
136     public download() {
137         if (this.apiRequest) {
138             var fileName = 'test_' + this.action + '_' + this.actionIdentifiers['vnf-id'] + '_request.json';
139             var theJSON = this.apiRequest;
140             if (fileName != null || fileName != '') {
141                 var blob = new Blob([theJSON], {
142                     type: 'text/json'
143                 });
144                 saveAs(blob, fileName);
145             }
146         }
147         else {
148             this.nService.error('Error', 'Please upload spreadsheet to download the request and response');
149         }
150
151         if (this.apiResponse) {
152             var fileName = 'test_' + this.action + '_' + this.actionIdentifiers['vnf-id'] + '_response.json';
153             var theJSON = this.apiResponse;
154             if (fileName != null || fileName != '') {
155                 var blob = new Blob([theJSON], {
156                     type: 'text/json'
157                 });
158                 saveAs(blob, fileName);
159             }
160         }
161
162     }
163
164
165     public abortTest() {
166         //this.apiResponse = "";
167         this.enableBrowse = true;
168         this.enableTestButton = true;
169         this.enablePollButton = true;
170         if (this.subscribe && this.subscribe != undefined) this.subscribe.unsubscribe();
171         this.apiResponse="Test has been abandoned and polling stopped";
172         this.nService.info("Information", "Test has been abandoned and polling stopped");
173     }
174
175
176     excelBrowseOption() {
177         $('#excelInputFile').trigger('click');
178     }
179
180
181     upload(evt: any) {
182         /* wire up file reader */
183         $('#filesparam').trigger('click');
184         const target: DataTransfer = <DataTransfer>(evt.target);
185         this.pollCounter = 0;
186         this.uploadFileName = evt.target.files[0].name;
187         var fileExtension = this.uploadFileName.substr(this.uploadFileName.lastIndexOf('.') + 1);
188
189         if (target.files.length != 1) {
190             throw new Error('Cannot upload multiple files on the entry');
191         }
192         if (fileExtension.toUpperCase() === 'XLS' || fileExtension.toUpperCase() === 'XLSX') {
193             this.spinner.show();
194             const reader = new FileReader();
195             reader.onload = (e: any) => {
196                 /* read workbook */
197                 const bstr = e.target.result;
198                 const wb = XLSX.read(bstr, { type: 'binary' });
199                 /* grab first sheet */
200                 const wsname = wb.SheetNames[0];
201                 const ws = wb.Sheets[wsname];
202
203                 /* save data */
204                 this.requestId = ''
205                 this.enableTestButton = true;
206                 this.enableAbort = true;
207                 this.enablePollButton = true;
208
209                 if (this.subscribe && this.subscribe != undefined) {
210                     this.enableCounterDiv = false;
211                     this.subscribe.unsubscribe();
212                 }
213                 this.apiRequest = '';
214                 this.apiResponse = '';
215                 this.showStatusResponseDiv = false;
216                 this.errorResponse = '';
217                 this.statusResponse = '';
218                 this.enableDownload = true;
219                 let arrData = (<AOA>(XLSX.utils.sheet_to_json(ws, { blankrows: false })));
220
221
222
223                 this.vmPayload = [];
224                 this.subPayload = {};
225                 this.vmJson = {};
226                 this.flag = 1;
227                 this.payload = {};
228                 this.oldListName1 = '';
229                 this.actionIdentifiers = {};
230                 // Refactor
231                 this.payload = this.processUploadedFile(arrData);
232                 this.uploadedFileResult();
233             };
234
235             reader.readAsBinaryString(target.files[0]);
236             setTimeout(() => {
237                         /** spinner ends after 2.5 seconds */
238                         this.spinner.hide();
239           }, 2500);
240
241         }
242         else {
243             this.nService.error('Error', 'Incorrect spreadsheet uploaded');
244             this.setValuesOnFileUploadFailure();
245         }
246     }
247
248     processUploadedFile(arrData) {
249         let tempPayload = {};
250         for (var i = 0; i < arrData.length; i++) {
251             var element = arrData[i];
252             if (element['TagName'] === 'action') {
253                 this.action = element['Value'];
254             }
255             if (element['List Name'] === 'action-identifiers') {
256                 this.vnfId = element['Value'];
257                 var key = element['TagName'];
258                 var value = element['Value'];
259                 if (key && value) {
260                     this.actionIdentifiers[key] = value;
261
262                 }
263             }
264
265             if (element['List Name'] === 'payload') {
266                 var listName1 = element['List Name_1'];
267                 var listName2 = element['List Name_2'];
268                 var listName3 = element['List Name_3'];
269                 var key = element['TagName'];
270                 var value = element['Value'];
271                 if (listName1) {
272                     if (this.oldListName1 == '' || (listName1 === this.oldListName1)) {
273                         this.constructTestPayload(listName2, listName3, key, value);
274                         tempPayload[listName1] = this.subPayload;
275                     }
276                     else {
277                         this.subPayload = {};
278                         this.constructTestPayload(listName2, listName3, key, value);
279                         tempPayload[listName1] = this.subPayload;
280                     }
281                     this.oldListName1 = listName1;
282                 }
283                 else {
284                     tempPayload[key] = value;
285                 }
286             }
287         }
288
289         return tempPayload;
290     }
291
292     uploadedFileResult() {
293         if (this.action && this.actionIdentifiers['vnf-id']) {
294             this.nService.success('Success', 'SpreadSheet uploaded successfully');
295         }
296         else {
297             this.setValuesOnFileUploadFailure();
298             this.nService.error("Error", "Please check the contents of the file uploaded")
299         }
300     }
301
302
303
304     constructTestPayload(listName2, listName3, key, value) {
305         if ((listName2 == undefined || listName2 == '') && (listName3 == undefined || listName3 == '')) {
306             this.subPayload[key] = value;
307         }
308         if (listName2) {
309
310             if (!listName3) {
311
312                 //vmPayload.push(vmJson)
313                 this.vmJson = {};
314                 this.vnfcJson = {};
315                 this.vmJson[key] = value;
316                 this.flag = 0;
317             }
318             else {
319                 this.vnfcJson[key] = value;
320                 this.vmJson['vnfc'] = [this.vnfcJson];
321                 this.flag = 1;
322             }
323             if (this.vmJson) this.lastvmJson = this.vmJson;
324             if (this.flag == 0) {
325                 this.vmPayload.push(this.lastvmJson);
326                 if (this.vmPayload) this.subPayload['vm'] = this.vmPayload;
327             }
328         }
329     }
330
331     constructRequest() {
332         this.timeStampInt = Date.now(); //.. milliseconds
333         let timeStamp;
334         console.log("constructRequest: isAppcTimestampReceived:" +
335             (this.isAppcTimestampReceived ? "true" : "false"));
336         if (this.isAppcTimestampReceived) {
337             console.log("constructRequest: AppcTimeDiff:[" + this.AppcTimeDiff + "]");
338             this.timeStampInt += this.AppcTimeDiff;
339             timeStamp = new Date(this.timeStampInt).toISOString();
340             console.log("constructRequest: got timeStamp from APPC:[" + timeStamp + "]");
341         }
342         else { //.. still not received
343             console.log('constructRequest: Appc Timestamp is not ready (use local)');
344             this.timeStampInt -= 100000;
345             timeStamp = new Date(this.timeStampInt).toISOString();
346         };
347         console.log('constructRequest: timeStamp:[' + timeStamp + ']');
348         let reqId;
349         this.requestId = reqId = new Date().getTime().toString();
350         let data = {
351             'input': {
352                 'common-header': {
353                     'timestamp': timeStamp,
354                     'api-ver': '2.00',
355                     'originator-id': this.userId,
356                     'request-id': this.requestId,
357                     'sub-request-id': this.requestId,
358                     'flags': {
359                         'mode': 'NORMAL',
360                         'force': this.force.toString().toUpperCase(),
361                         'ttl': 3600
362                     }
363                 },
364                 'action': this.action,
365                 'action-identifiers': this.actionIdentifiers,
366                 'payload': JSON.stringify(this.payload)
367             }
368         };
369         if (this.action == 'Unlock') {
370             let payload = JSON.parse(data.input['payload']);
371             data.input['common-header']['request-id'] = payload['request-id'];
372             data.input['common-header']['sub-request-id'] = payload['request-id'];
373         }
374
375         if(this.action == 'Unlock' || this.action == 'Lock' || this.action == 'CheckLock') {
376             delete data.input['payload'];
377         }
378
379         return data;
380     }
381
382     testVnf() {
383         this.enableBrowse = false;
384         this.enableTestButton = false;
385         this.enablePollButton = false;
386         this.timer = Observable.interval(10000);
387         if(this.action == 'Unlock' || this.action == 'Lock' || this.action == 'CheckLock') {
388             this.enablePollButton = true;
389             this.enableBrowse = true;
390             this.enableTestButton = true;
391             this.requestId = '';
392         } else {
393             this.subscribe = this.timer.subscribe((t) => this.pollTestStatus());
394         }
395         this.ngProgress.start();
396         this.apiRequest = JSON.stringify(this.constructRequest());
397
398         this.httpUtil.post(
399             {
400                 url: environment.testVnf + "?urlAction=" + this.getUrlEndPoint(this.action),
401                 data: this.apiRequest
402             })
403             .subscribe(resp => {
404                 this.apiResponse = JSON.stringify(resp);
405                 this.enableBrowse = true;
406                 this.enableTestButton = true;
407                 this.ngProgress.done();
408             },
409                 error => {
410                     this.nService.error('Error', 'Error in connecting to APPC Server');
411                     // this.enableBrowse = true;
412                     this.enableTestButton = true;
413                     this.enablePollButton = true;
414                     this.enableCounterDiv = false;
415                     this.enableBrowse = true;
416                     if (this.subscribe && this.subscribe != undefined) this.subscribe.unsubscribe();
417
418                 });
419
420         setTimeout(() => {
421             this.ngProgress.done();
422         }, 3500);
423     }
424
425     getAppcTimestamp() {
426         this.timeStampInt = Date.now(); //.. milliseconds
427         console.log("getAppcTimestamp: timeStampInt:[" + this.timeStampInt + "]");
428         let timeStampP = new Date(this.timeStampInt).toISOString();
429         console.log("getAppcTimestamp: from int timestamp:[" + timeStampP + "]");
430         this.isAppcTimestampReceived = false;
431         let reqId = new Date().getTime().toString();
432         try {
433             let data = {
434                 'input': {
435                     'design-request': {
436                         'request-id': reqId,
437                         'action': 'getAppcTimestampUTC',
438                         'payload': '{}'
439                     }
440                 }
441             };
442             console.log('getAppcTimestamp: sending httpUtil.post...');
443             this.httpUtil.post(
444                 {
445                     url: environment.getDesigns, data: data
446                 })
447                 .subscribe(resp => {
448                     this.appcTimestampResponse = resp;
449                     // this.appcTimestampResponse = JSON.stringify(resp);
450                     console.log('appcTimestampResponse:[' + resp + ']');
451                     this.parseAppcTimestamp(this.appcTimestampResponse);
452                 });
453         }
454         catch (e) {
455             this.nService.warn('status',
456                 'Error while retrieving APPC Timestamp(using local by default)!');
457         }
458     }
459
460     parseAppcTimestamp(tstampStr: string) {
461         //.. parse the response to get timestamp as milliseconds
462         // input format: YYYY-MM-DDTHH:mm:ss.sssZ (24 chars)
463         var rexp =
464             new RegExp(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z/);
465         var mresult = rexp.exec(tstampStr);
466         if (mresult[0]) {
467             console.log("parseAppcTimestamp: response format is OK...");
468             var aYearS = mresult[1];
469             var aYear = parseInt(aYearS, 10);
470             var aMonS = mresult[2];
471             var aMon = parseInt(aMonS, 10) - 1;
472             var aDayS = mresult[3];
473             var aDay = parseInt(aDayS, 10);
474             var aHrS = mresult[4];
475             var aHr = parseInt(aHrS, 10);
476             var aMntS = mresult[5];
477             var aMnt = parseInt(aMntS, 10);
478             var aSecS = mresult[6];
479             var aSec = parseInt(aSecS, 10);
480             var aMsecS = mresult[7];
481             var aMsec = parseInt(aMsecS, 10);
482             this.AppcTimeStampInt =
483                 Date.UTC(aYear, aMon, aDay, aHr, aMnt, aSec, aMsec);
484             console.log(
485                 "parseAppcTimestamp: AppcTimeStampInt:[" + this.AppcTimeStampInt + "]");
486             let timeStampP = new Date(this.AppcTimeStampInt).toISOString();
487             console.log("parseAppcTimestamp: from int timestamp:[" + timeStampP + "]");
488             //.. AppcTimeDiff - time difference in milliseconds
489             this.AppcTimeDiff = this.AppcTimeStampInt - this.timeStampInt;
490             console.log("parseAppcTimestamp: AppcTimeDiff:[" + this.AppcTimeDiff + "]");
491             this.isAppcTimestampReceived = true;
492         }
493         else {
494             throw new Error(
495                 'The received APPC Timestamp is not matching expected format: YYYY-MM-DDTHH:mm:ss.sssZ !');
496         }
497     }
498
499     pollTestStatus() {
500         if (this.requestId && this.actionIdentifiers['vnf-id']) {
501             // console.log("payload==" + JSON.stringify(this.payload))
502             this.timeStampInt = Date.now(); //.. milliseconds
503             let timeStamp;
504             console.log("pollTestStatus: isAppcTimestampReceived:" +
505                 (this.isAppcTimestampReceived ? "true" : "false"));
506             if (this.isAppcTimestampReceived) {
507                 this.timeStampInt += this.AppcTimeDiff;
508                 timeStamp = new Date(this.timeStampInt).toISOString();
509                 console.log("pollTestStatus: got timeStamp from APPC:[" + timeStamp + "]");
510             }
511             else { //.. still not received
512                 console.log('pollTestStatus: Appc Timestamp is not ready (use local)');
513                 this.timeStampInt -= 100000;
514                 timeStamp = new Date(this.timeStampInt).toISOString();
515             };
516             console.log("pollTestStatus: timestamp:[" + timeStamp + "]");
517             let reqId = new Date().getTime().toString();
518             let data = {
519                 'input': {
520                     'common-header': {
521                         'timestamp': timeStamp,
522                         'api-ver': '2.00',
523                         'originator-id': this.userId,
524                         'request-id': reqId,
525                         'sub-request-id': reqId,
526                         'flags': {
527                             'mode': 'NORMAL',
528                             'force': this.force.toString().toUpperCase(),
529                             'ttl': 3600
530                         }
531                     },
532                     'action': 'ActionStatus',
533                     'action-identifiers': {
534                         'vnf-id': this.actionIdentifiers['vnf-id']
535                     },
536                     'payload': '{"request-id":' + this.requestId + '}'
537                 }
538             };
539             this.httpUtil.post(
540                 {
541                     url: environment.checkTestStatus, data: data
542
543                 })
544                 .subscribe(resp => {
545                     this.statusResponse = JSON.stringify(resp);
546                     var status = ''
547                     var statusReason = ''
548                     this.enableCounterDiv = true;
549                     this.pollCounter++;
550                     if (resp.output) var timeStamp = resp.output['common-header'].timestamp;
551                     if (resp.output.payload) {
552                         var payload = resp.output.payload.replace(/\\/g, "")
553                         try {
554                             payload = JSON.parse(payload)
555                             status = payload['status'];
556                             statusReason = payload['status-reason'];
557                         }
558                         catch (err) {
559                             console.log("error" + err)
560                         }
561                     }
562                     if (timeStamp && status && statusReason) {
563                         this.showStatusResponseDiv = true;
564                         this.outputTimeStamp = timeStamp;
565                         this.status = status;
566                         this.statusReason = statusReason;
567                         if (status.toUpperCase() === 'SUCCESS' || status.toUpperCase() === 'SUCCESSFUL') {
568                             if (this.subscribe && this.subscribe != undefined) this.subscribe.unsubscribe();
569                             this.enablePollButton = true;
570                             this.enableBrowse = true;
571                             this.enableTestButton = true;
572                         }
573                         if (status.toUpperCase() === 'FAILED') {
574                             if (this.subscribe && this.subscribe != undefined) this.subscribe.unsubscribe();
575                             this.enablePollButton = true;
576                             this.enableBrowse = true;
577                             this.enableTestButton = true;
578                         }
579                     }
580                     else {
581                         this.showStatusResponseDiv = false;
582                         if (this.subscribe && this.subscribe != undefined) {
583                             this.subscribe.unsubscribe();
584                             this.enablePollButton = true;
585                         }
586
587                     }
588
589                 },
590                     error => {
591                         this.statusResponse = null;
592                         this.showStatusResponseDiv = false;
593                         this.errorResponse = 'Error Connecting to APPC server';
594                         this.enableCounterDiv = false;
595                         this.enableBrowse = true;
596                         this.enableTestButton = true;
597                         if (this.subscribe && this.subscribe != undefined) {
598                             this.subscribe.unsubscribe();
599                             this.enablePollButton = true;
600                         }
601                     });
602
603         }
604         else {
605             this.nService.error("Error", "Please enter vnf Id & request Id");
606         }
607
608     }
609
610     getUrlEndPoint(action) {
611         let charArray = action.split('');
612         let url = '';
613         for (let i = 0; i < charArray.length; i++) {
614             if (charArray[i] == charArray[i].toUpperCase() && i != 0) {
615                 url = url + '-';
616             }
617             url = url + charArray[i];
618         }
619
620         return url.toLowerCase();
621     }
622
623     setValuesOnFileUploadFailure() {        
624         this.flag = 1;
625         this.oldListName1 = '';
626         this.vmJson = {};
627         this.vnfcJson = {};
628         this.subPayload = {};
629         this.vmPayload = [];
630         this.payload = {};
631         this.action = '';
632         this.actionIdentifiers = {};
633         this.apiRequest = '';
634         this.apiResponse = '';
635         this.enableCounterDiv = false;
636         this.enableAbort = false;
637         this.enableTestButton = false;
638         this.enableDownload = false;
639     }
640
641 }