blob: d7711234e8882952d26fc3748b113ba21e281e52 [file] [log] [blame]
kumaran.m3b4814a2020-05-01 19:48:54 +05301/*
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 Compose Component
20 */
kumaran.m3b4814a2020-05-01 19:48:54 +053021import { HttpHeaders } from '@angular/common/http';
22import { Component, ElementRef, Injector, ViewChild, ViewEncapsulation } from '@angular/core';
23import { ActivatedRoute, Router } from '@angular/router';
24import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
25import { TranslateService } from '@ngx-translate/core';
26import { NotifierService } from 'angular-notifier';
27import { APIURLHEADER, CONSTANTNUMBER, ERRORDATA, MODALCLOSERESPONSEDATA, MODALCLOSERESPONSEWITHCP } from 'CommonModel';
28import { ConfirmationTopologyComponent } from 'ConfirmationTopology';
29import * as d3 from 'd3';
30import { DataService } from 'DataService';
31import { environment } from 'environment';
32import * as HttpStatus from 'http-status-codes';
33import * as jsyaml from 'js-yaml';
Barath Kumar R063a3f12020-12-29 16:35:09 +053034import {
35 CCI,
36 COMPOSERNODES,
37 DF,
38 GRAPHDETAILS,
39 NSData,
40 NSDATACREATION,
41 NSDDetails,
42 Tick, TickPath, VLC, VLD, VNFPROFILE
43} from 'NSDModel';
kumaran.m3b4814a2020-05-01 19:48:54 +053044import { RestService } from 'RestService';
45import { SharedService } from 'SharedService';
46import { isNullOrUndefined } from 'util';
Barath Kumar R063a3f12020-12-29 16:35:09 +053047import { VNFD, VNFData } from 'VNFDModel';
kumaran.m3b4814a2020-05-01 19:48:54 +053048
49/**
50 * Creating component
51 * @Component takes NSComposerComponent.html as template url
52 */
53@Component({
54 selector: 'app-ns-composer',
55 templateUrl: './NSComposerComponent.html',
56 styleUrls: ['./NSComposerComponent.scss'],
57 encapsulation: ViewEncapsulation.None
58})
59/** Exporting a class @exports NSComposerComponent */
60export class NSComposerComponent {
61 /** To inject services @public */
62 public injector: Injector;
63 /** View child contains graphContainer ref @public */
64 @ViewChild('graphContainer', { static: true }) public graphContainer: ElementRef;
65 /** dataService to pass the data from one component to another @public */
66 public dataService: DataService;
67 /** Contains VNFD Informations @public */
Barath Kumar R063a3f12020-12-29 16:35:09 +053068 public nsPackageDetails: NSData = { id: '', name: '', description: '', version: '', designer: '' };
kumaran.m3b4814a2020-05-01 19:48:54 +053069 /** Contains VL Details @public */
Barath Kumar R063a3f12020-12-29 16:35:09 +053070 public virtualLinkDesc: VLD = {
71 id: '',
72 'mgmt-network': true
kumaran.m3b4814a2020-05-01 19:48:54 +053073 };
74 /** Contains the information of the type of modification @public */
75 public putType: string;
76 /** Conatins mousedown action @public */
77 public mousedownNode: COMPOSERNODES = null;
78 /** Conatins mouseup action @public */
79 public mouseupNode: COMPOSERNODES = null;
80 /** Conatins mousedownLink action @public */
81 public mousedownLink: COMPOSERNODES = null;
82 /** Conatins current Selection node action @public */
83 public currentSelectedNode: COMPOSERNODES = null;
84 /** Conatins current Selection node action @public */
85 public currentSelectedLink: COMPOSERNODES = null;
86 /** Need to show the NSD Details @public */
87 public isShowNSDDetails: boolean = true;
88 /** Contains the node information of VL @public */
89 public vlNodes: {}[] = [];
90 /** Need to show the VL Details @public */
91 public isShowVLDetails: boolean = false;
92 /** Contains the node information of VNF @public */
93 public vnfNodes: {}[] = [];
94 /** contains the VNF Details @public */
Barath Kumar R063a3f12020-12-29 16:35:09 +053095 public vnfData: VNFPROFILE;
96 /** contains the Virtual Link connectivity Details @public */
97 public virtualLinkProfileID: string;
kumaran.m3b4814a2020-05-01 19:48:54 +053098 /** Need to show the VNF Details @public */
99 public isShowVNFDetails: boolean = false;
100 /** Contains the node information of CP @public */
101 public cpNodes: {}[] = [];
102 /** Need to show the CP Details */
Barath Kumar R063a3f12020-12-29 16:35:09 +0530103 public cpData: CCI;
kumaran.m3b4814a2020-05-01 19:48:54 +0530104 /** Need to show the VNF Details @public */
105 public isShowCPDetails: boolean = false;
106 /** random number count @public */
107 public randomNumberLength: number;
108 /** Contains the vnfd information @public */
Barath Kumar R063a3f12020-12-29 16:35:09 +0530109 public vnfList: VNFD[] = [];
kumaran.m3b4814a2020-05-01 19:48:54 +0530110 /** Add the activeclass for the selected @public */
111 public activeClass: string = 'active';
112 /** Add the fixed class for the freeze @public */
113 public fixedClass: string = 'fixed';
114 /** Check the loading results @public */
115 public isLoadingResults: boolean = true;
116 /** Give the message for the loading @public */
117 public message: string = 'PLEASEWAIT';
118 /** Get VNF selected node @public */
Barath Kumar R063a3f12020-12-29 16:35:09 +0530119 public getVNFSelectedData: VNFD;
kumaran.m3b4814a2020-05-01 19:48:54 +0530120 /** Assign the forcesimulation active @public */
121 public forceSimulationActive: boolean = false;
122 /** Assign pinned class for the button when freezed @public */
123 public classApplied: boolean = false;
124 /** Contains sidebar open status @public */
125 public sideBarOpened: boolean = false;
126 /** Contains SVG attributes @private */
127 // tslint:disable-next-line:no-any
128 private svg: any;
129 /** Contains the Drag line */
130 // tslint:disable-next-line: no-any
131 private dragLine: any;
132 /** Contains VL node @private */
133 // tslint:disable-next-line:no-any
134 private vlNode: any;
135 /** Contains VNFD node @private */
136 // tslint:disable-next-line:no-any
137 private vnfdnode: any;
138 /** Contains CP node @private */
139 // tslint:disable-next-line:no-any
140 private cpnode: any;
141 /** Rendered nodes represent VL @private */
142 // tslint:disable-next-line:no-any
143 private gvlNode: any;
144 /** Rendered nodes represent VL @private */
145 // tslint:disable-next-line:no-any
146 private gvnfdNode: any;
147 /** Rendered nodes represent VL @private */
148 // tslint:disable-next-line:no-any
149 private gcpNode: any;
150 /** Contains forced node animations @private */
151 // tslint:disable-next-line:no-any
152 private force: any;
153 /** Contains all the selected node @private */
154 private selectedNode: COMPOSERNODES[] = [];
kumaran.m3b4814a2020-05-01 19:48:54 +0530155 /** Contains the connected point @private */
156 private connectionPoint: string;
kumaran.m3b4814a2020-05-01 19:48:54 +0530157 /** Contains id of the node @private */
158 private identifier: string;
kumaran.m3b4814a2020-05-01 19:48:54 +0530159 /** Contains copy of NSD information @private */
160 private nsdCopy: string;
161 /** Contains the VNFD copy @private */
162 private vnfdCopy: string;
kumaran.m3b4814a2020-05-01 19:48:54 +0530163 /** Contains path information of the node */
164 // tslint:disable-next-line:no-any
165 private path: any;
166 /** Contains the node information @private */
167 private nodes: COMPOSERNODES[] = [];
168 /** Contains the link information of nodes @private */
169 private links: {}[] = [];
170 /** Contains the NS information @private */
171 private nsData: NSDDetails;
172 /** Instance of the rest service @private */
173 private restService: RestService;
174 /** Service holds the router information @private */
175 private router: Router;
176 /** Holds teh instance of AuthService class of type AuthService @private */
177 private activatedRoute: ActivatedRoute;
178 /** Notifier service to popup notification @private */
179 private notifierService: NotifierService;
180 /** Controls the header form @private */
181 private headers: HttpHeaders;
182 /** Contains tranlsate instance @private */
183 private translateService: TranslateService;
184 /** Contains lastkeypressed instance @private */
185 private lastKeyDown: number = -1;
186 /** Instance of the modal service @private */
187 private modalService: NgbModal;
188 /** Setting the Value of connection point refrence of the CP @private */
189 private setVnfdConnectionPointRef: string;
190 /** Setting the Value of VL name for confirmation @private */
191 private vlName: string;
192 /** Setting the Value of VNFD name for confirmation @private */
193 private setVnfdName: string;
194 /** Contains all methods related to shared @private */
195 private sharedService: SharedService;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530196 /** Contains selected node VNF profile objects @private */
197 private selectedVNFProfile: VNFPROFILE[];
kumaran.m3b4814a2020-05-01 19:48:54 +0530198
199 constructor(injector: Injector) {
200 this.injector = injector;
201 this.restService = this.injector.get(RestService);
202 this.dataService = this.injector.get(DataService);
203 this.router = this.injector.get(Router);
204 this.activatedRoute = this.injector.get(ActivatedRoute);
205 this.notifierService = this.injector.get(NotifierService);
206 this.translateService = this.injector.get(TranslateService);
207 this.modalService = this.injector.get(NgbModal);
208 this.sharedService = this.injector.get(SharedService);
209 }
harshini.r92d376d2022-04-05 12:35:14 +0530210 /** Lifecyle Hooks the trigger before component is instantiated @public */
kumaran.m3b4814a2020-05-01 19:48:54 +0530211 public ngOnInit(): void {
212 // tslint:disable-next-line:no-backbone-get-set-outside-model
213 this.identifier = this.activatedRoute.snapshot.paramMap.get('id');
214 this.generateData();
215 this.headers = new HttpHeaders({
harshini.r92d376d2022-04-05 12:35:14 +0530216 'Content-Type': 'application/gzip',
kumaran.m3b4814a2020-05-01 19:48:54 +0530217 Accept: 'application/json',
218 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
219 });
220 }
221 /** Events handles at drag on D3 region @public */
222 // tslint:disable-next-line:no-any
223 public drag(ev: any): void {
224 if (ev.target.id === 'vl') {
225 ev.dataTransfer.setData('text', ev.target.id);
226 } else {
227 ev.dataTransfer.setData('text', ev.target.attributes['data-id'].value);
228 }
229 }
230 /** On clicking redirect to NS edit page @public */
231 public onEdit(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530232 this.router.navigate(['/packages/ns/edit/', this.identifier]).catch((): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530233 // Catch Navigation Error
234 });
235 }
236 /** Events handles drop at D3 region @public */
237 public drop(ev: DragEvent): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530238 ev.preventDefault();
239 const getDropedName: string = ev.dataTransfer.getData('text');
240 if (getDropedName === 'vl') {
kumaran.m3b4814a2020-05-01 19:48:54 +0530241 this.svg.selectAll('*').remove();
242 this.vldropComposer();
243 } else {
244 this.svg.selectAll('*').remove();
Barath Kumar R063a3f12020-12-29 16:35:09 +0530245 const vnfdName: string = ev.dataTransfer.getData('text');
246 this.vnfdropComposer(vnfdName);
kumaran.m3b4814a2020-05-01 19:48:54 +0530247 }
248 }
249 /** Drop VL Composer Data @public */
250 public vldropComposer(): void {
251 this.randomNumberLength = CONSTANTNUMBER.randomNumber;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530252 const generateId: string = 'ns_vl_' + this.sharedService.randomString();
253 if (this.nsData['virtual-link-desc'] === undefined) {
254 this.nsData['virtual-link-desc'] = [];
kumaran.m3b4814a2020-05-01 19:48:54 +0530255 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530256 this.nsData['virtual-link-desc'].push({
257 id: generateId,
258 'mgmt-network': false
259 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530260 this.putType = 'nsdadd';
261 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
262 }
263 /** Drop VNFD Composer Data @public */
Barath Kumar R063a3f12020-12-29 16:35:09 +0530264 public vnfdropComposer(vnfdName: string): void {
265 const vnfID: string = 'ns_vnfd_' + this.sharedService.randomString();
266 if (this.nsData.df.length > 0) {
267 this.addVNFDID(vnfdName);
268 this.nsData.df.forEach((res: DF): void => {
269 if (res['vnf-profile'] === undefined) {
270 res['vnf-profile'] = [];
271 }
272 res['vnf-profile'].push({
273 id: vnfID,
274 'virtual-link-connectivity': [],
275 'vnfd-id': vnfdName
276 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530277 });
278 } else {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530279 Object.assign(this.nsData.df, {
280 id: 'default-df',
281 'vnf-profile': [{
282 id: vnfID,
283 'virtual-link-connectivity': [],
284 'vnfd-id': vnfdName
kumaran.m3b4814a2020-05-01 19:48:54 +0530285 }]
286 });
287 }
288 this.putType = 'vnfdadd';
289 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
290 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530291 /** Add the VNFD-ID while drop VNFD if not exists @public */
292 public addVNFDID(vnfdName: string): void {
293 const vnfdIDArray: string[] = this.nsData['vnfd-id'];
294 if (vnfdIDArray !== undefined) {
295 if (vnfdIDArray.indexOf(vnfdName) === -1) {
296 vnfdIDArray.push(vnfdName);
297 }
298 } else {
299 Object.assign(this.nsData, {
300 'vnfd-id': [vnfdName]
301 });
302 }
303 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530304 /** Events handles allow drop on D3 region @public */
305 public allowDrop(ev: DragEvent): void {
306 ev.preventDefault();
307 }
308 /** Save NSD Information @public */
309 public saveNSD(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530310 if (this.nsPackageDetails.id !== undefined) {
311 this.nsData.id = this.nsPackageDetails.id;
kumaran.m3b4814a2020-05-01 19:48:54 +0530312 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530313 if (this.nsPackageDetails.name !== undefined) {
314 this.nsData.name = this.nsPackageDetails.name;
kumaran.m3b4814a2020-05-01 19:48:54 +0530315 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530316 if (this.nsPackageDetails.description !== undefined) {
317 this.nsData.description = this.nsPackageDetails.description;
kumaran.m3b4814a2020-05-01 19:48:54 +0530318 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530319 if (this.nsPackageDetails.version !== undefined) {
320 this.nsData.version = this.nsPackageDetails.version;
kumaran.m3b4814a2020-05-01 19:48:54 +0530321 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530322 if (this.nsPackageDetails.designer !== undefined) {
323 this.nsData.designer = this.nsPackageDetails.designer;
kumaran.m3b4814a2020-05-01 19:48:54 +0530324 }
325 this.putType = 'nsdUpdate';
326 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
327 }
328 /** Save Virtual Link @public */
329 public saveVL(vlid: string): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530330 this.nsData['virtual-link-desc'].forEach((result: VLD): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530331 if (result.id === vlid) {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530332 result['mgmt-network'] = !isNullOrUndefined(this.virtualLinkDesc['mgmt-network']) ? this.virtualLinkDesc['mgmt-network'] : true;
kumaran.m3b4814a2020-05-01 19:48:54 +0530333 }
334 });
335 this.putType = 'vlUpdate';
336 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
337 }
338 /** Add the new Data @public */
339 public addData(apiURL: string, identifier: string, data: NSDDetails, putType: string): void {
340 this.isLoadingResults = true;
341 let successMessage: string = '';
342 if (putType === 'nsdadd') {
343 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDNSD';
344 } else if (putType === 'vnfdadd') {
345 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDVNFD';
346 } else if (putType === 'cpAdded') {
347 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.ADDNS';
348 } else if (putType === 'nsdUpdate') {
349 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.UPDATEDSUCCESSFULLY';
350 } else if (putType === 'vlUpdate') {
351 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.UPDATEDSUCCESSFULLY';
352 } else if (putType === 'nsddelete') {
353 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETENSD';
354 } else if (putType === 'vnfddelete') {
355 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETEVNFD';
356 } else if (putType === 'nsdelete') {
357 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETENS';
358 } else if (putType === 'linkdelete') {
359 successMessage = 'PAGE.NSPACKAGE.NSCOMPOSE.DELETELINK';
360 }
361 /** Below hide for conflicts with light weight UI */
362 const apiURLHeader: APIURLHEADER = {
363 url: apiURL + '/' + identifier + '/nsd_content',
364 httpOptions: { headers: this.headers }
365 };
Barath Kumar R063a3f12020-12-29 16:35:09 +0530366 const nsData: NSDATACREATION = { nsd: { nsd: [] } };
367 nsData.nsd.nsd = [];
368 nsData.nsd.nsd.push(data);
369 const descriptorInfo: string = jsyaml.dump(nsData, { sortKeys: true });
kumaran.m3b4814a2020-05-01 19:48:54 +0530370 this.sharedService.targzFile({ packageType: 'nsd', id: this.identifier, descriptor: descriptorInfo })
371 .then((content: ArrayBuffer): void => {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530372 this.restService.putResource(apiURLHeader, content).subscribe((res: {}): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530373 this.generateData();
374 this.notifierService.notify('success', this.translateService.instant(successMessage));
375 this.isLoadingResults = false;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530376 }, (error: ERRORDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530377 this.generateData();
378 this.restService.handleError(error, 'put');
379 this.isLoadingResults = false;
380 });
381 }).catch((): void => {
382 this.notifierService.notify('error', this.translateService.instant('ERROR'));
383 this.isLoadingResults = false;
384 });
385 }
386 /** Show Info @public */
387 public showInfo(): void {
388 const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
389 modalRef.componentInstance.topologyType = 'Info';
390 modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.INFO');
Barath Kumar R063a3f12020-12-29 16:35:09 +0530391 modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530392 if (result) {
393 // empty
394 }
395 }).catch();
396 }
397 /** Event to freeze the animation @public */
398 public onFreeze(): void {
399 this.classApplied = !this.classApplied;
400 const alreadyFixedIsActive: boolean = d3.select('svg#graphContainer').classed(this.fixedClass);
401 d3.select('svg#graphContainer').classed(this.fixedClass, !alreadyFixedIsActive);
402 if (alreadyFixedIsActive) {
403 this.force.stop();
404 }
405 this.forceSimulationActive = alreadyFixedIsActive;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530406 this.nodes.forEach((d: COMPOSERNODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530407 d.fx = (alreadyFixedIsActive) ? null : d.x;
408 d.fy = (alreadyFixedIsActive) ? null : d.y;
409 });
410 if (alreadyFixedIsActive) {
411 this.force.restart();
412 }
413 }
414 /** Events handles when dragended @public */
415 public toggleSidebar(): void {
416 this.sideBarOpened = !this.sideBarOpened;
417 this.deselectAllNodes();
418 this.showRightSideInfo(true, false, false, false);
419 }
420 /** Prepare information for node creation of VNFD @private */
421 private generateData(): void {
422 this.generateVNFData();
423 this.generateDataNSDTopology();
424 this.sideBarOpened = false;
425 }
426 /** Prepare the information of the VNFD @private */
427 private generateVNFData(): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530428 this.restService.getResource(environment.VNFPACKAGESCONTENT_URL).subscribe((vnfdPackageData: VNFD[]): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530429 this.vnfList = vnfdPackageData;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530430 }, (error: ERRORDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530431 this.restService.handleError(error, 'get');
432 });
433 }
434 /** Prepare information for node creation of NSD Topology @private */
435 private generateDataNSDTopology(): void {
436 this.nodes = [];
437 this.links = [];
Barath Kumar R063a3f12020-12-29 16:35:09 +0530438 this.restService.getResource(environment.NSDESCRIPTORSCONTENT_URL + '/' + this.identifier).subscribe((nsData: NSDDetails): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530439 delete nsData._admin;
440 delete nsData._id;
Barath Kumar R218e8812020-09-02 16:43:05 +0530441 delete nsData._links;
kumaran.m3b4814a2020-05-01 19:48:54 +0530442 this.nsData = nsData;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530443 this.generateNSInfo(nsData);
444 if (nsData['virtual-link-desc'] !== undefined) {
kumaran.m3b4814a2020-05-01 19:48:54 +0530445 /** Details of the VL */
446 this.nsDataVLD(nsData);
447 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530448 if (this.nsData.df.length > 0) {
449 this.nsData.df.forEach((res: DF): void => {
450 if (res['vnf-profile'] !== undefined) {
451 /** Details of the VNFD */
452 this.nsDataConstituentVNFD(nsData);
453 }
454 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530455 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530456 if (nsData.df.length > 0) {
kumaran.m3b4814a2020-05-01 19:48:54 +0530457 this.nsDataVLDLinkCreation(nsData);
458 }
459 this.separateAndCreatenode();
Barath Kumar R063a3f12020-12-29 16:35:09 +0530460 }, (error: ERRORDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530461 if (error.error.status === HttpStatus.NOT_FOUND || error.error.status === HttpStatus.UNAUTHORIZED) {
462 this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
463 } else {
464 this.restService.handleError(error, 'get');
465 }
466 this.isLoadingResults = false;
467 this.isShowNSDDetails = false;
468 });
469 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530470 /** Generate the NS Package Information */
471 private generateNSInfo(nsData: NSDDetails): void {
472 this.nsPackageDetails.id = nsData.id;
473 this.nsPackageDetails.name = nsData.name;
474 this.nsPackageDetails.description = nsData.description;
475 this.nsPackageDetails.version = nsData.version;
476 this.nsPackageDetails.designer = nsData.designer;
477 }
478 /** nsData VL node creation function @private */
kumaran.m3b4814a2020-05-01 19:48:54 +0530479 private nsDataVLD(nsData: NSDDetails): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530480 nsData['virtual-link-desc'].forEach((res: VLD): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530481 this.nodes.push({ id: res.id, reflexive: false, type: 'vld', name: res.id, selectorId: res.id });
kumaran.m3b4814a2020-05-01 19:48:54 +0530482 });
483 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530484 /** nsData VNFD node creation function @private */
kumaran.m3b4814a2020-05-01 19:48:54 +0530485 private nsDataConstituentVNFD(nsData: NSDDetails): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530486 nsData.df.forEach((resDF: DF): void => {
487 resDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
488 this.nodes.push(
489 {
490 id: resVNF['vnfd-id'] + ':' + resVNF.id,
491 reflexive: false,
492 type: 'vnfd',
493 name: resVNF['vnfd-id'],
494 nodeIndex: resVNF.id,
495 selectorId: resVNF['vnfd-id'] + '_' + resVNF.id
496 });
497 if (resVNF['virtual-link-connectivity'] !== undefined) {
498 this.nsDataCP(resVNF, resVNF.id);
499 }
500 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530501 });
502 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530503 /** nsData CP node creation function @private */
504 private nsDataCP(resVNF: VNFPROFILE, vnfID: string): void {
505 resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
506 resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
507 this.nodes.push(
508 {
509 id: vnfID + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'],
510 reflexive: false,
511 type: 'ns',
512 name: resultCCI['constituent-cpd-id'],
513 nodeIndex: resultCCI['constituent-base-element-id'],
514 selectorId: 'osm-' + resultCCI['constituent-cpd-id'] + '-' + vnfID + resultCCI['constituent-base-element-id'] + index
515 });
516 });
517 });
518 }
519 /** nsData Link node creation function @private */
kumaran.m3b4814a2020-05-01 19:48:54 +0530520 private nsDataVLDLinkCreation(nsData: NSDDetails): void {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530521 nsData.df.forEach((resDF: DF): void => {
522 if (resDF['vnf-profile'] !== undefined) {
523 resDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
524 this.nsdCopy = resVNF['vnfd-id'] + ':' + resVNF.id;
525 if (resVNF['virtual-link-connectivity'] !== undefined) {
526 this.nsDataVNFDConnectionPointRefrence(resVNF);
527 }
528 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530529 }
530 });
531 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530532 /** nsDataVNFDConnectionPointRefrence undefined Call this function @private */
533 private nsDataVNFDConnectionPointRefrence(resVNF: VNFPROFILE): void {
534 resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
535 resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
536 this.vnfdCopy = resultVLC['virtual-link-profile-id'];
537 this.connectionPoint = resVNF.id + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'];
538 const connectionPointPos: number = this.nodes.map((e: COMPOSERNODES): string => { return e.id; }).indexOf(this.connectionPoint);
539 const nsdPos: number = this.nodes.map((e: COMPOSERNODES): string => { return e.id; }).indexOf(this.nsdCopy);
540 const vnfdPos: number = this.nodes.map((e: COMPOSERNODES): string => { return e.id; }).indexOf(this.vnfdCopy);
541 this.links.push(
542 {
543 source: this.nodes[connectionPointPos],
544 target: this.nodes[nsdPos]
545 },
546 {
547 source: this.nodes[connectionPointPos],
548 target: this.nodes[vnfdPos]
549 });
550 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530551 });
552 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530553 /** Separate and create node @private */
554 private separateAndCreatenode(): void {
555 this.seprateNodes(this.nodes);
556 this.createnode(this.nodes);
557 this.isLoadingResults = false;
558 }
559 /** Get the default Configuration of containers @private */
560 private getGraphContainerAttr(): GRAPHDETAILS {
561 return {
562 width: 700,
563 height: 400,
564 nodeHeight: 50,
565 nodeWidth: 35,
566 textX: -35,
567 textY: 30,
568 radius: 5,
569 distance: 50,
570 strength: -500,
571 forcex: 2,
572 forcey: 2,
573 sourcePaddingYes: 17,
574 sourcePaddingNo: 12,
575 targetPaddingYes: 4,
576 targetPaddingNo: 3,
577 alphaTarget: 0.3,
578 imageX: -25,
579 imageY: -25,
580 shiftKeyCode: 17
581 };
582 }
583 /** Separate the nodes along with its tyep @private */
584 private seprateNodes(node: COMPOSERNODES[]): void {
585 this.vlNodes = []; this.vnfNodes = []; this.cpNodes = [];
Barath Kumar R063a3f12020-12-29 16:35:09 +0530586 node.forEach((nodeList: COMPOSERNODES): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530587 if (nodeList.type === 'vld') {
588 this.vlNodes.push(nodeList);
589 } else if (nodeList.type === 'vnfd') {
590 this.vnfNodes.push(nodeList);
591 } else if (nodeList.type === 'ns') {
592 this.cpNodes.push(nodeList);
593 }
594 });
595 }
596 /** Node is created and render at D3 region @private */
597 private createnode(node: COMPOSERNODES[]): void {
598 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
599 d3.selectAll('svg#graphContainer > *').remove();
Barath Kumar R063a3f12020-12-29 16:35:09 +0530600 d3.select(window).on('keydown', (): void => { this.keyDown(); });
601 d3.select(window).on('keyup', (): void => { this.keyUp(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530602 this.svg = d3.select('#graphContainer')
603 .attr('oncontextmenu', 'return false;')
Barath Kumar R063a3f12020-12-29 16:35:09 +0530604 .attr('viewBox', `0 0 ${graphContainerAttr.width} ${graphContainerAttr.height}`)
605 .on('mousemove', (): void => { this.mousemove(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530606 this.force = d3.forceSimulation()
607 .force('charge', d3.forceManyBody().strength(graphContainerAttr.strength))
Barath Kumar R063a3f12020-12-29 16:35:09 +0530608 .force('link', d3.forceLink().id((d: TickPath): string => d.id).distance(graphContainerAttr.distance))
kumaran.m3b4814a2020-05-01 19:48:54 +0530609 .force('center', d3.forceCenter(graphContainerAttr.width / graphContainerAttr.forcex,
610 graphContainerAttr.height / graphContainerAttr.forcey))
611 .force('x', d3.forceX(graphContainerAttr.width / graphContainerAttr.forcex))
612 .force('y', d3.forceY(graphContainerAttr.height / graphContainerAttr.forcey))
Barath Kumar R063a3f12020-12-29 16:35:09 +0530613 .on('tick', (): void => { this.tick(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530614 this.dragLine = this.svg.append('svg:path').attr('class', 'link dragline hidden').attr('d', 'M0,0L0,0');
615 this.path = this.svg.append('svg:g').selectAll('path');
616 this.vlNode = this.svg.append('svg:g').selectAll('vlnode');
617 this.vnfdnode = this.svg.append('svg:g').selectAll('vnfdnode');
618 this.cpnode = this.svg.append('svg:g').selectAll('cpnode');
619 // app starts here
620 this.restart(node);
621 }
622 /** update force layout (called automatically each iteration) @private */
623 private tick(): void {
624 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
625 // draw directed edges with proper padding from node centers
Barath Kumar R063a3f12020-12-29 16:35:09 +0530626 this.path.attr('class', 'link').attr('d', (d: Tick): string => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530627 const deltaX: number = d.target.x - d.source.x;
628 const deltaY: number = d.target.y - d.source.y;
629 const dist: number = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
630 const normX: number = deltaX / dist;
631 const normY: number = deltaY / dist;
632 const sourcePadding: number = d.left ? graphContainerAttr.sourcePaddingYes : graphContainerAttr.sourcePaddingNo;
633 const targetPadding: number = d.right ? graphContainerAttr.targetPaddingYes : graphContainerAttr.targetPaddingNo;
634 const sourceX: number = d.source.x + (sourcePadding * normX);
635 const sourceY: number = d.source.y + (sourcePadding * normY);
636 const targetX: number = d.target.x - (targetPadding * normX);
637 const targetY: number = d.target.y - (targetPadding * normY);
638 return `M${sourceX},${sourceY}L${targetX},${targetY}`;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530639 }).on('dblclick', (d: Tick): void => { this.getDeleteLinkConfirmation(d); });
640 this.vlNode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
641 this.vnfdnode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
642 this.cpnode.attr('transform', (t: TickPath): string => `translate(${t.x},${t.y})`);
kumaran.m3b4814a2020-05-01 19:48:54 +0530643 }
644 /** Update graph (called when needed) at D3 region @private */
645 private restart(node: COMPOSERNODES[]): void {
646 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
647 this.path = this.path.data(this.links);
Barath Kumar R063a3f12020-12-29 16:35:09 +0530648 this.vlNode = this.vlNode.data(this.vlNodes, (d: COMPOSERNODES): string => d.id);
649 this.vnfdnode = this.vnfdnode.data(this.vnfNodes, (d: COMPOSERNODES): string => d.id);
650 this.cpnode = this.cpnode.data(this.cpNodes, (d: COMPOSERNODES): string => d.id);
kumaran.m3b4814a2020-05-01 19:48:54 +0530651 this.resetAndCreateNodes();
652 this.force.nodes(node).force('link').links(this.links);
653 this.force.alphaTarget(graphContainerAttr.alphaTarget).restart();
654 }
655 /** Rest and create nodes @private */
656 private resetAndCreateNodes(): void {
657 this.path.exit().remove();
658 this.vlNode.exit().remove();
659 this.vnfdnode.exit().remove();
660 this.cpnode.exit().remove();
661 this.getPathNodes();
662 this.getVLNodes();
663 this.getVNFDNodes();
664 this.getCPNodes();
665 this.path.merge(this.path);
666 this.vlNode = this.gvlNode.merge(this.vlNode);
667 this.vnfdnode = this.gvnfdNode.merge(this.vnfdnode);
668 this.cpnode = this.gcpNode.merge(this.cpnode);
669 }
670 /** setting the Path @private */
671 private getPathNodes(): void {
672 this.path = this.path.enter().append('svg:path');
673 }
674 /** Setting all the VL nodes @private */
675 private getVLNodes(): void {
676 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
677 this.gvlNode = this.vlNode.enter().append('svg:g');
678 this.gvlNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
679 this.gvlNode.append('svg:image')
680 .style('opacity', 1)
681 .attr('x', graphContainerAttr.imageX)
682 .attr('y', graphContainerAttr.imageY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530683 .call(this.onDragDrop())
684 .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; })
kumaran.m3b4814a2020-05-01 19:48:54 +0530685 .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
686 .attr('xlink:href', 'assets/images/VL.svg')
Barath Kumar R063a3f12020-12-29 16:35:09 +0530687 .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
688 .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
689 .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.vlNode, d); this.onNodeClickToggleSidebar(); })
690 .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530691 this.gvlNode.append('svg:text')
692 .attr('class', 'node_text')
693 .attr('y', graphContainerAttr.textY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530694 .text((d: COMPOSERNODES): string => d.id);
kumaran.m3b4814a2020-05-01 19:48:54 +0530695 }
696 /** Setting all the VNFD nodes @private */
697 private getVNFDNodes(): void {
698 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
699 this.gvnfdNode = this.vnfdnode.enter().append('svg:g');
700 this.gvnfdNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
701 this.gvnfdNode.append('svg:image')
702 .style('opacity', 1)
703 .attr('x', graphContainerAttr.imageX)
704 .attr('y', graphContainerAttr.imageY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530705 .call(this.onDragDrop())
706 .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; })
kumaran.m3b4814a2020-05-01 19:48:54 +0530707 .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
708 .attr('xlink:href', 'assets/images/VNFD.svg')
Barath Kumar R063a3f12020-12-29 16:35:09 +0530709 .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
710 .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
711 .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.vnfdnode, d); this.onNodeClickToggleSidebar(); })
712 .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530713 this.gvnfdNode.append('svg:text')
714 .attr('class', 'node_text')
715 .attr('y', graphContainerAttr.textY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530716 .text((d: COMPOSERNODES): string => d.name);
kumaran.m3b4814a2020-05-01 19:48:54 +0530717 }
718 /** Setting all the CP nodes @private */
719 private getCPNodes(): void {
720 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
721 this.gcpNode = this.cpnode.enter().append('svg:g');
722 this.gcpNode.append('svg:circle').attr('r', graphContainerAttr.radius).style('fill', '#eeeeee');
723 this.gcpNode.append('svg:image')
724 .style('opacity', 1)
725 .attr('x', graphContainerAttr.imageX)
726 .attr('y', graphContainerAttr.imageY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530727 .call(this.onDragDrop())
728 .attr('id', (d: COMPOSERNODES): string => { return d.selectorId; })
kumaran.m3b4814a2020-05-01 19:48:54 +0530729 .attr('class', 'node').attr('width', graphContainerAttr.nodeWidth).attr('height', graphContainerAttr.nodeHeight)
730 .attr('xlink:href', 'assets/images/CP.svg')
Barath Kumar R063a3f12020-12-29 16:35:09 +0530731 .on('mousedown', (d: COMPOSERNODES): void => { this.mouseDown(d); })
732 .on('mouseup', (d: COMPOSERNODES): void => { this.mouseUp(d); })
733 .on('click', (d: COMPOSERNODES): void => { this.singleClick(this.cpnode, d); this.onNodeClickToggleSidebar(); })
734 .on('dblclick', (d: COMPOSERNODES): void => { this.getDeleteConfirmation(d); this.onNodedblClickToggleSidebar(); });
kumaran.m3b4814a2020-05-01 19:48:54 +0530735 this.gcpNode.append('svg:text')
736 .attr('class', 'node_text')
737 .attr('y', graphContainerAttr.textY)
Barath Kumar R063a3f12020-12-29 16:35:09 +0530738 .text((d: COMPOSERNODES): string => d.name);
kumaran.m3b4814a2020-05-01 19:48:54 +0530739 }
740 /** Events handles when mousemove it will capture the selected node data @private */
741 private mousemove(): void {
742 if (!this.mousedownNode) { return; }
743 this.dragLine.attr('d',
744 `M${this.mousedownNode.x},${this.mousedownNode.y}L${d3.mouse(d3.event.currentTarget)[0]},${d3.mouse(d3.event.currentTarget)[1]}`);
745 }
746 /** Get confirmation Before Deleting the Link in Topology @private */
Barath Kumar R063a3f12020-12-29 16:35:09 +0530747 private getAddConfirmation(mouseData: COMPOSERNODES, getNsData: NSDDetails, addType: string, getVLDIndex: string): void {
kumaran.m3b4814a2020-05-01 19:48:54 +0530748 let findVNFName: string = '';
749 let findVLDID: string = '';
750 if (mouseData.type === 'vld') {
751 findVNFName = this.mouseupNode.name;
752 findVLDID = this.mousedownNode.id;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530753 this.vlName = this.mousedownNode.name;
kumaran.m3b4814a2020-05-01 19:48:54 +0530754 } else {
755 findVNFName = this.mousedownNode.name;
756 findVLDID = this.mouseupNode.id;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530757 this.vlName = this.mouseupNode.name;
kumaran.m3b4814a2020-05-01 19:48:54 +0530758 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530759 if (getNsData['vnfd-id'] !== undefined) {
760 getNsData['vnfd-id'].forEach((resVNFid: string): void => {
761 if (resVNFid === findVNFName) {
762 this.getVNFSelectedData = this.vnfList.filter((vnfList: VNFD): boolean => vnfList.id === findVNFName)[0];
763 this.setVnfdConnectionPointRef = this.getVNFSelectedData['mgmt-cp'];
764 this.setVnfdName = this.getVNFSelectedData['product-name'];
765 this.selectedVNFProfile = getNsData.df[0]['vnf-profile'];
766 }
767 });
768 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530769 if (this.vlName !== undefined && this.setVnfdName !== undefined && this.setVnfdConnectionPointRef !== undefined) {
770 const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
771 modalRef.componentInstance.topologyType = 'Add';
Barath Kumar R063a3f12020-12-29 16:35:09 +0530772 modalRef.componentInstance.cpDetails = this.getVNFSelectedData['ext-cpd'];
kumaran.m3b4814a2020-05-01 19:48:54 +0530773 this.translateService.get('PAGE.TOPOLOGY.ADDINGCP', {
774 vlname: '<b>' + this.vlName + '</b>',
775 vnfdname: '<b>' + this.setVnfdName + '</b>',
776 cpname: '<b>' + this.setVnfdConnectionPointRef + '</b>'
Barath Kumar R063a3f12020-12-29 16:35:09 +0530777 }).subscribe((res: string): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530778 modalRef.componentInstance.topologyname = res;
779 });
780 modalRef.componentInstance.topologytitle = this.translateService.instant('PAGE.TOPOLOGY.CONNECTIONPOINT');
Barath Kumar R063a3f12020-12-29 16:35:09 +0530781 modalRef.result.then((result: MODALCLOSERESPONSEWITHCP): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530782 if (result) {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530783 this.generateCPForVNF(this.selectedVNFProfile, result.connection_point, getVLDIndex);
kumaran.m3b4814a2020-05-01 19:48:54 +0530784 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, getNsData, addType);
785 } else {
786 this.deselectPath();
787 }
788 }).catch();
789 } else {
790 this.deselectPath();
791 this.notifierService.notify('error', this.translateService.instant('ERROR'));
792 }
793 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530794 /** Generate connection point for vnf using vld @private */
Barath Kumar R063a3f12020-12-29 16:35:09 +0530795 private generateCPForVNF(result: VNFPROFILE[], cp: string, getVLDIndex: string): void {
796 if (result !== undefined) {
797 result.forEach((resultVNFPROFILE: VNFPROFILE, index: number): void => {
798 if (getVLDIndex === resultVNFPROFILE.id) {
799 resultVNFPROFILE['virtual-link-connectivity'].push({
800 'constituent-cpd-id': [{
801 'constituent-base-element-id': getVLDIndex,
802 'constituent-cpd-id': cp
803 }],
804 'virtual-link-profile-id': this.vlName
805 });
806 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530807 });
808 } else {
809 Object.assign(result, {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530810 'virtual-link-connectivity': [{
811 'constituent-cpd-id': [{
812 'constituent-base-element-id': getVLDIndex,
813 'constituent-cpd-id': cp
814 }],
815 'virtual-link-profile-id': this.vlName
kumaran.m3b4814a2020-05-01 19:48:54 +0530816 }]
817 });
818 }
819 }
kumaran.m3b4814a2020-05-01 19:48:54 +0530820 /** Events handles when mousedown click it will capture the selected node data @private */
821 private mouseDown(d: COMPOSERNODES): void {
822 event.preventDefault();
823 if (d3.event.ctrlKey) { return; }
824 if (d3.event.shiftKey) {
825 if (d.type === 'vnfd') {
826 this.selectedNode.push(d);
827 }
828 this.mousedownNode = d;
829 this.currentSelectedNode = (this.mousedownNode === this.currentSelectedNode) ? null : this.mousedownNode;
830 this.currentSelectedLink = null;
831 this.dragLine.style('marker-end', 'url(#end-arrow)').classed('hidden', false)
832 .attr('d', `M${this.mousedownNode.x},${this.mousedownNode.y}L${this.mousedownNode.x},${this.mousedownNode.y}`);
833 }
834 }
835 /** Event handles when mouseup event occures @private */
836 private mouseUp(d: COMPOSERNODES): void {
837 if (!this.mousedownNode) { return; }
838 this.dragLine.classed('hidden', true).style('marker-end', '');
839 this.mouseupNode = d;
840 if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vnfd') {
841 const getOldVLDIndex: string[] = this.mouseupNode.id.split(':');
Barath Kumar R063a3f12020-12-29 16:35:09 +0530842 const setOldVLDindex: string = getOldVLDIndex[1];
kumaran.m3b4814a2020-05-01 19:48:54 +0530843 this.putType = 'cpAdded';
844 this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex);
845 } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vld') {
846 const getOldVLDIndex: string[] = this.mousedownNode.id.split(':');
Barath Kumar R063a3f12020-12-29 16:35:09 +0530847 const setOldVLDindex: string = getOldVLDIndex[1];
kumaran.m3b4814a2020-05-01 19:48:54 +0530848 this.putType = 'cpAdded';
849 this.getAddConfirmation(this.mousedownNode, this.nsData, this.putType, setOldVLDindex);
850 } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'ns') {
851 this.deselectPath();
852 this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNFCP'));
853 } else if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'ns') {
854 this.deselectPath();
855 this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNFCP'));
856 } else if (this.mousedownNode.type === 'vld' && this.mouseupNode.type === 'vld') {
857 this.deselectPath();
858 this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVL'));
859 } else if (this.mousedownNode.type === 'vnfd' && this.mouseupNode.type === 'vnfd') {
860 this.deselectPath();
861 this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVNF'));
862 } else if (this.mousedownNode.type === 'ns' && this.mouseupNode.type === 'ns') {
863 this.deselectPath();
864 this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKCP'));
865 } else {
866 this.deselectPath();
867 this.notifierService.notify('warning', this.translateService.instant('PAGE.NSPACKAGE.NSCOMPOSE.CANNOTLINKVLVNF'));
868 }
869 this.resetMouseVars();
870 // select new link
871 this.currentSelectedLink = d;
872 this.currentSelectedNode = null;
873 }
874 /** Mosue Drag Line false if it is not satisfied @private */
875 private deselectPath(): void {
876 this.dragLine.classed('hidden', true).style('marker-end', '').attr('d', 'M0,0L0,0');
877 }
878 /** reset Mouse varaibles @private */
879 private resetMouseVars(): void {
880 this.mousedownNode = null;
881 this.mouseupNode = null;
882 this.mousedownLink = null;
883 }
884 /** De-select all the selected nodes @private */
885 private deselectAllNodes(): void {
886 this.vlNode.select('image').classed(this.activeClass, false);
887 this.vnfdnode.select('image').classed(this.activeClass, false);
888 this.cpnode.select('image').classed(this.activeClass, false);
889 }
890 /** Show the right-side information @private */
891 private showRightSideInfo(nsdDetails: boolean, vldDetails: boolean, vnfDeails: boolean, cpDetails: boolean): void {
892 this.isShowNSDDetails = nsdDetails;
893 this.isShowVLDetails = vldDetails;
894 this.isShowVNFDetails = vnfDeails;
895 this.isShowCPDetails = cpDetails;
896 }
897 /** Events handles when Shift Click to perform create cp @private */
898 // tslint:disable-next-line: no-any
899 private singleClick(nodeSelected: any, d: COMPOSERNODES): void {
900 this.selectNodeExclusive(nodeSelected, d);
901 }
902 /** Selected nodes @private */
903 // tslint:disable-next-line: no-any
904 private selectNodeExclusive(nodeSeleced: any, d: COMPOSERNODES): void {
905 const alreadyIsActive: boolean = nodeSeleced.select('#' + d.selectorId).classed(this.activeClass);
906 this.deselectAllNodes();
907 nodeSeleced.select('#' + d.selectorId).classed(this.activeClass, !alreadyIsActive);
908 if (d.type === 'vld' && !alreadyIsActive) {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530909 this.nsData['virtual-link-desc'].forEach((result: VLD): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530910 if (result.id === d.id) {
911 this.showRightSideInfo(false, true, false, false);
Barath Kumar R063a3f12020-12-29 16:35:09 +0530912 this.virtualLinkDesc = result;
kumaran.m3b4814a2020-05-01 19:48:54 +0530913 }
914 });
915 } else if (d.type === 'vnfd' && !alreadyIsActive) {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530916 this.nsData.df.forEach((res: DF): void => {
917 if (res['vnf-profile'] !== undefined) {
918 res['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
919 if (resVNF.id === d.nodeIndex && resVNF['vnfd-id'] === d.name) {
920 this.showRightSideInfo(false, false, true, false);
921 this.vnfData = resVNF;
922 }
923 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530924 }
925 });
926 } else if (d.type === 'ns' && !alreadyIsActive) {
Barath Kumar R063a3f12020-12-29 16:35:09 +0530927 this.nsData.df.forEach((resultDF: DF): void => {
928 if (resultDF['vnf-profile'] !== undefined) {
929 resultDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
930 if (resVNF['virtual-link-connectivity'] !== undefined) {
931 resVNF['virtual-link-connectivity'].forEach((resultVLC: VLC, index: number): void => {
932 resultVLC['constituent-cpd-id'].forEach((resultCCI: CCI): void => {
933 const connectionPointID: string = resVNF.id + ':' + resultCCI['constituent-base-element-id'] + index + ':' + resultCCI['constituent-cpd-id'];
934 if (connectionPointID === d.id) {
935 this.cpData = resultCCI;
936 this.vnfData = resVNF;
937 this.virtualLinkProfileID = resultVLC['virtual-link-profile-id'];
938 this.showRightSideInfo(false, false, false, true);
939 }
940 });
941 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530942 }
943 });
944 }
945 });
946 } else {
947 this.showRightSideInfo(true, false, false, false);
948 }
949 }
950 /** Get confirmation Before Deleting the Link in Topology @private */
951 private getDeleteLinkConfirmation(d: Tick): void {
952 const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
953 modalRef.componentInstance.topologyType = 'Delete';
Barath Kumar R063a3f12020-12-29 16:35:09 +0530954 modalRef.componentInstance.topologyname = this.translateService.instant('PAGE.TOPOLOGY.LINK') + ' - ' + d.source.id;
kumaran.m3b4814a2020-05-01 19:48:54 +0530955 modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.LINK';
Barath Kumar R063a3f12020-12-29 16:35:09 +0530956 modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +0530957 if (result) {
958 this.doubleClickLink(d);
959 }
960 }).catch();
961 }
962 /** Events handles when Double Click to Delete the link @private */
963 private doubleClickLink(d: Tick): void {
964 let getID: string = '';
Barath Kumar R063a3f12020-12-29 16:35:09 +0530965 let getName: string = '';
966 let getNodeIndex: string;
967 if (d.source.type === 'ns') {
kumaran.m3b4814a2020-05-01 19:48:54 +0530968 getID = d.source.id;
Barath Kumar R063a3f12020-12-29 16:35:09 +0530969 getName = d.source.name;
970 getNodeIndex = d.source.nodeIndex;
kumaran.m3b4814a2020-05-01 19:48:54 +0530971 }
Barath Kumar R063a3f12020-12-29 16:35:09 +0530972 /** Split the selected node of connectionpoint */
973 const selectedNode: string[] = getID.split(':');
974 this.nsData.df.forEach((resultDF: DF): void => {
975 if (resultDF['vnf-profile'] !== undefined) {
976 resultDF['vnf-profile'].forEach((elementVNF: VNFPROFILE): void => {
977 const selectedVNFProfileID: string = selectedNode[0];
978 /** If VNF ID is equal to selected VNFProfile ID check the VLC of CCI to match the id and name to remove the VLC index */
979 if (selectedVNFProfileID === elementVNF.id) {
980 elementVNF['virtual-link-connectivity'].forEach((elementVLC: VLC, index: number): void => {
981 const posCCI: number = elementVLC['constituent-cpd-id'].findIndex((e: CCI): boolean => {
982 const getCID: string = elementVNF.id + ':' + e['constituent-base-element-id'] + index + ':' + e['constituent-cpd-id'];
983 return getID === getCID;
984 });
985 if (posCCI !== -1) {
986 elementVNF['virtual-link-connectivity'].splice(index, 1);
987 }
988 });
989 }
990 });
kumaran.m3b4814a2020-05-01 19:48:54 +0530991 }
992 });
993 this.putType = 'linkdelete';
994 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
995 }
996 /** Get confirmation Before Deleting the Node in Topology @private */
997 private getDeleteConfirmation(d: COMPOSERNODES): void {
998 const modalRef: NgbModalRef = this.modalService.open(ConfirmationTopologyComponent, { backdrop: 'static' });
999 modalRef.componentInstance.topologyType = 'Delete';
1000 modalRef.componentInstance.topologyname = d.name;
1001 if (d.type === 'vld') {
1002 modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VIRTUALLINK';
1003 } else if (d.type === 'vnfd') {
1004 modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.VNF';
1005 } else if (d.type === 'ns') {
1006 modalRef.componentInstance.topologytitle = 'PAGE.TOPOLOGY.CONNECTIONPOINT';
1007 }
Barath Kumar R063a3f12020-12-29 16:35:09 +05301008 modalRef.result.then((result: MODALCLOSERESPONSEDATA): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +05301009 if (result) {
1010 this.doubleClick(d);
1011 }
1012 }).catch();
1013 }
1014 /** Events handles when Double Click to Delete @private */
1015 private doubleClick(d: COMPOSERNODES): void {
1016 const deletedNode: COMPOSERNODES = d;
Barath Kumar R063a3f12020-12-29 16:35:09 +05301017 this.nodes.forEach((res: COMPOSERNODES, i: number): void => {
kumaran.m3b4814a2020-05-01 19:48:54 +05301018 if (res.id === d.id) {
1019 if (deletedNode.type === 'vld') {
Barath Kumar R063a3f12020-12-29 16:35:09 +05301020 /** Remove the virtual-link-desc related to VL */
1021 const pos: number = this.nsData['virtual-link-desc'].map((e: VLD): string => { return e.id; }).indexOf(d.id);
1022 this.nsData['virtual-link-desc'].splice(pos, 1);
1023 /** Remove the virtual-link-connectivity between VL and VNFD */
1024 this.nsData.df.forEach((resultDF: DF): void => {
1025 if (resultDF['vnf-profile'] !== undefined) {
1026 resultDF['vnf-profile'].forEach((resVNF: VNFPROFILE): void => {
1027 const getVLArray: number[] = resVNF['virtual-link-connectivity'].map((e: VLC, index: number): number => {
1028 if (e['virtual-link-profile-id'] === d.id) {
1029 return index;
1030 }
1031 });
1032 if (getVLArray.length > 0) {
1033 getVLArray.forEach((removeIndex: number): void => {
1034 const index: string = removeIndex.toString();
1035 resVNF['virtual-link-connectivity'].splice(resVNF['virtual-link-connectivity'][index], 1);
1036 });
1037 }
1038 });
1039 }
1040 });
kumaran.m3b4814a2020-05-01 19:48:54 +05301041 this.putType = 'nsddelete';
1042 } else if (deletedNode.type === 'vnfd') {
Barath Kumar R063a3f12020-12-29 16:35:09 +05301043 this.nsData.df.forEach((resultDF: DF): void => {
1044 if (resultDF['vnf-profile'] !== undefined) {
1045 /** Remove the vnf-profile related to VNFD */
1046 const posVNF: number = resultDF['vnf-profile'].findIndex((e: VNFPROFILE): boolean => {
1047 return e['vnfd-id'] === d.name && e.id === d.nodeIndex;
1048 });
1049 resultDF['vnf-profile'].splice(posVNF, 1);
1050 /** Check the VNFD exists in any vnf-profile */
1051 const isVNFDExists: boolean = resultDF['vnf-profile'].some((e: VNFPROFILE): boolean => {
1052 return e['vnfd-id'] === d.name;
1053 });
1054 /** If VNFD not exists in the vnf-profile remove from vnfd-id */
1055 if (!isVNFDExists) {
1056 const posVNFD: number = this.nsData['vnfd-id'].findIndex((e: string): boolean => {
1057 return e === d.name;
kumaran.m3b4814a2020-05-01 19:48:54 +05301058 });
Barath Kumar R063a3f12020-12-29 16:35:09 +05301059 this.nsData['vnfd-id'].splice(posVNFD, 1);
kumaran.m3b4814a2020-05-01 19:48:54 +05301060 }
Barath Kumar R063a3f12020-12-29 16:35:09 +05301061 }
1062 });
kumaran.m3b4814a2020-05-01 19:48:54 +05301063 this.putType = 'vnfddelete';
1064 } else if (deletedNode.type === 'ns') {
Barath Kumar R063a3f12020-12-29 16:35:09 +05301065 /** Split the selected node */
1066 const selectedNode: string[] = d.id.split(':');
1067 this.nsData.df.forEach((resultDF: DF): void => {
1068 if (resultDF['vnf-profile'] !== undefined) {
1069 resultDF['vnf-profile'].forEach((elementVNF: VNFPROFILE): void => {
1070 const selectedVNFProfileID: string = selectedNode[0];
1071 /** If VNF ID is equal to selected VNFProfile ID check the VLC of CCI to match the id and name to remove the VLC index */
1072 if (selectedVNFProfileID === elementVNF.id) {
1073 elementVNF['virtual-link-connectivity'].forEach((elementVLC: VLC, index: number): void => {
1074 const posCCI: number = elementVLC['constituent-cpd-id'].findIndex((e: CCI): boolean => {
1075 const getID: string = elementVNF.id + ':' + e['constituent-base-element-id'] + index + ':' + e['constituent-cpd-id'];
1076 return d.id === getID;
1077 });
1078 if (posCCI !== -1) {
1079 elementVNF['virtual-link-connectivity'].splice(index, 1);
1080 }
1081 });
1082 }
1083 });
1084 }
1085 });
kumaran.m3b4814a2020-05-01 19:48:54 +05301086 this.putType = 'nsdelete';
1087 }
1088 this.addData(environment.NSDESCRIPTORS_URL, this.identifier, this.nsData, this.putType);
1089 }
1090 });
1091 }
Barath Kumar R063a3f12020-12-29 16:35:09 +05301092 /** drag event @private */
1093 // tslint:disable-next-line: no-any
1094 private onDragDrop(): any {
1095 return d3.drag().filter(this.dragFilter)
1096 .on('start', this.dragstarted)
1097 .on('drag', this.dragged)
1098 .on('end', this.dragended);
1099 }
kumaran.m3b4814a2020-05-01 19:48:54 +05301100 /** Key press event @private */
1101 private keyDown(): void {
1102 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
1103 if (this.lastKeyDown !== -1) { return; }
1104 this.lastKeyDown = d3.event.keyCode;
1105 if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
kumaran.m3b4814a2020-05-01 19:48:54 +05301106 this.svg.classed('ctrl', true);
1107 }
1108 }
1109 /** Key realse event @private */
1110 private keyUp(): void {
1111 const graphContainerAttr: GRAPHDETAILS = this.getGraphContainerAttr();
1112 this.lastKeyDown = -1;
1113 if (d3.event.keyCode === graphContainerAttr.shiftKeyCode) {
1114 this.gvlNode.on('.drag', null);
1115 this.gvnfdNode.on('.drag', null);
1116 this.gcpNode.on('.drag', null);
1117 this.svg.classed('ctrl', false);
1118 }
1119 }
Barath Kumar R063a3f12020-12-29 16:35:09 +05301120 /** Events handles when to drag using filter for the keys @private */
1121 private dragFilter(): boolean {
1122 return d3.event.ctrlKey && !d3.event.button;
1123 }
kumaran.m3b4814a2020-05-01 19:48:54 +05301124 /** Events handles when dragstarted @private */
1125 private dragstarted(d: COMPOSERNODES): void {
1126 d.fx = d.x;
1127 d.fy = d.y;
1128 }
1129 /** Events handles when dragged @private */
1130 private dragged(d: COMPOSERNODES): void {
1131 d.fx = d.x = d3.event.x;
1132 d.fy = d.y = d3.event.y;
1133 }
1134 /** Events handles when dragended @private */
1135 private dragended(d: COMPOSERNODES): void {
1136 if (this.forceSimulationActive) {
1137 d.fx = null;
1138 d.fy = null;
1139 } else {
1140 d.fx = d.x;
1141 d.fy = d.y;
1142 this.forceSimulationActive = false;
1143 }
1144 }
1145 /** Events handles when node double click @private */
1146 private onNodedblClickToggleSidebar(): void {
1147 this.sideBarOpened = false;
1148 }
1149 /** Events handles when node single click @private */
1150 private onNodeClickToggleSidebar(): void {
1151 this.sideBarOpened = true;
1152 }
1153}