rebuild GUI structure(only changed modules' name)
[vnfsdk/refrepo.git] / catalog / src / main / webapp / catalog / js / template / topoUtil.js
1 /*
2  * Copyright 2016-2017 ZTE Corporation.
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 var topoUtil = {};
17 topoUtil.topoDatas=[];
18 topoUtil.svgOffsetWidth = 0;
19
20 /**
21  * recursive generate tree structure of the topology graph data
22  * @param  {[type]} rootName [description]
23  * @param  {[type]} rootNode [description]
24  * @return {[type]}          [description]
25  */
26 topoUtil.generateSortData = function(rootName,rootNode) {
27     for(var i=0;i<topoUtil.topoDatas.length;i++) {
28                 if(topoUtil.topoDatas[i].containIn == rootName){
29                         rootNode["children"].push(topoUtil.topoDatas[i]);       
30                         var currentNum = rootNode["children"].length-1; 
31                         topoUtil.generateSortData(topoUtil.topoDatas[i].id, rootNode["children"][currentNum])
32                 }
33     }
34 }
35
36 /**
37  * generate CP data, CP is inserted into the VDU or VNF child nodes
38  * @param  {[type]} cpNode   [description]
39  * @param  {[type]} rootNode [description]
40  * @return {[type]}          [description]
41  */
42 topoUtil.generateCpData = function(cpNode, rootNode) {
43     for(var i=0;i<cpNode.length;i++){
44                 for(var j=0;j<rootNode.length;j++) {
45                         var node = rootNode[j];
46                         if(cpNode[i].virtualbindsto == node.id) {
47                                 rootNode[j].cp.push(cpNode[i]);
48                                 break;
49                         }                                       
50                 }
51     }
52 }
53
54 /**
55  * generate NETWORK and VL data, VL is inserted into the NETWORK child nodes
56  * @param  {[type]} rootNode [description]
57  * @return {[type]}          [description]
58  */
59 topoUtil.generateNetworkData = function(vlanNode, networkNode) {
60         if(networkNode.length == 0) {
61                 //no NETWORK, just VL
62                 var network = {
63                         subnets : vlanNode
64                 }
65                 networkNode.push(network);
66         } else {
67                 //NETWORK and VL
68                 for(var i=0;i<networkNode.length;i++) {
69                         networkNode[i].subnets = [];
70                         for(var j=0;j<vlanNode.length;j++){
71                                 var network = vlanNode[j].virtuallinksto;
72                                 if(network == networkNode[i].id) {
73                                         networkNode[i].subnets.push(vlanNode[j]);
74                                 }
75                     }
76                 }
77         }
78 }
79
80 /**
81  * initialize topology graph data
82  * @param  {[type]} resp             [description]
83  * @param  {[type]} nodeInstanceData [description]
84  * @return {[type]}                  [description]
85  */
86 topoUtil.initTopoData = function(resp, nodeInstanceData) {
87         if(resp && resp.length > 0) {
88                 var datas = resp;
89                 var boxData = [];
90                 var networks = [];
91                 var vlanData = [];
92                 var cpData = [];
93         for(var i=0;i<datas.length;i++){        
94                 if (datas[i]["containIn"] == "") {
95                         datas[i]["containIn"] = "--";
96                 }
97                 //add the property of children for all nodes
98             datas[i]["children"] = [];
99             datas[i]["cp"] = [];
100             //count instances number
101             if (nodeInstanceData) {
102                 datas[i]["num"] = topoUtil.getInstanceNum(datas[i], nodeInstanceData);
103             }
104             //empty currentLinkNum
105             datas[i]["currentLinkNum"] = 0; 
106             //distinguish VL, CP, NETWORK, VNF, VDU, VNFC from nodes to display topology graph
107             var type = datas[i]["type"];
108                         if (type.toUpperCase().indexOf(".VL") > -1) {
109                                 vlanData.push(datas[i]);
110                         } else if (type.toUpperCase().indexOf(".CP") > -1) {
111                                 cpData.push(datas[i]);
112                         } else if(type.toUpperCase().indexOf(".NETWORK") > -1) {
113                                 networks.push(datas[i]);
114                         } else if ((type.toUpperCase().indexOf(".VNF") > -1) || (type.toUpperCase().indexOf(".VDU") > -1) 
115                                 || (type.toUpperCase().indexOf(".VNFC") > -1)) {
116                                 boxData.push(datas[i]);
117                         } else {
118                                 boxData.push(datas[i]);
119                         }
120         }
121         
122                 //generate CP nodes
123                 topoUtil.generateCpData(cpData, boxData);
124                 //generate VNF/NS tree data
125         var rootNode = {"children":[]};
126         topoUtil.topoDatas = boxData;
127                 topoUtil.generateSortData("--", rootNode);
128                 vm.topologyTab.boxTopoDatas = rootNode.children;
129                 //generate NETWORK and VL nodes
130                 topoUtil.generateNetworkData(vlanData, networks);
131                 vm.topologyTab.networkTopoDatas = networks;
132
133         //draw topology graph
134         topoUtil.topoDatas = datas;
135         setTimeout("topoUtil.generateLine()", 100);
136         //bind window object events
137         topoUtil.initWindowEvent();
138         }
139 }
140
141 /**
142  * get node instances number
143  * @param  {[type]} nodeTemplate     [description]
144  * @param  {[type]} nodeInstanceData [description]
145  * @return {[type]}                  [description]
146  */
147 topoUtil.getInstanceNum = function(nodeTemplate, nodeInstanceData) {
148         var num = 0;
149         var id;
150         if(nodeTemplate.properties && nodeTemplate.properties.vnfdid) {
151                 id = nodeTemplate.properties.vnfdid;
152         } else {
153                 id = nodeTemplate.id;
154         }
155         
156         if(nodeInstanceData && nodeInstanceData.length > 0) {
157                 for (var j=0;j<nodeInstanceData.length;j++) {
158                         if(nodeInstanceData[j].nodeTemplateId == id) {
159                                 num++;
160                         }
161                 }
162         }
163         return num;
164 }
165
166 topoUtil.getLineOffset = function(index) {
167         return  index*15;
168 }
169 /**
170  * get node y coordinate offset, it is based on the total number of connections and the number of connections to 
171  * calculate the Y coordinate offset current connection
172  * here's the connection refers connectsto relationship between VNC and VNC
173  * @param  {[type]} node   current node object
174  * @param  {[type]} height current DOM object cliengtHeight
175  * @return {[type]}        Y coordinate offset
176  */
177 topoUtil.getNodeOffset = function(node, height) {
178         var toNodeLinkNum = ++node.currentLinkNum;
179         var totalLinkNum = node.inLinks.length + node.outLinks.length;
180         totalLinkNum++;
181         return (height/totalLinkNum)*toNodeLinkNum;
182 }
183 /**
184  * get node object by name
185  * @param  {[type]} name node name
186  * @return {[type]}      node object data
187  */
188 topoUtil.getTopoDataById = function(id) {
189         var node;
190         for(var i=0;i<topoUtil.topoDatas.length;i++) {
191                 if(id == topoUtil.topoDatas[i].id) {
192                         node = topoUtil.topoDatas[i];
193                 }
194         }
195         return  node;
196 }
197
198 topoUtil.pageX = function(elem) {
199         return  elem.offsetParent ? (elem.offsetLeft + topoUtil.pageX(elem.offsetParent)) : elem.offsetLeft;
200 }
201
202 topoUtil.pageY = function(elem) {
203         return  elem.offsetParent ? (elem.offsetTop + topoUtil.pageY(elem.offsetParent)) : elem.offsetTop;
204 }
205
206 topoUtil.getHorizontalOffset = function(elem, elemArray) {
207         var horizontalOffset = 0;
208         for(var i=0;i<elemArray.length;i++) {
209                 var nodeTop = topoUtil.pageY(elemArray[i]);
210                 var fromTop = topoUtil.pageY(elem);
211                 if(fromTop == nodeTop) {
212                         horizontalOffset = topoUtil.getLineOffset(++horizontalIndex);
213                 }
214         }
215         return horizontalOffset;
216 }
217
218 topoUtil.getParentNode = function(elem) {
219         return elem.className == "app" ? topoUtil.getParentNode(elem.offsetParent) : elem.offsetParent;
220 }
221
222 topoUtil.initElementSize = function() {
223         var height=$(".bpContainer").height();
224     $(".vlan").height() < height ? $(".vlan").height(height) : height;
225
226     var networkWidth = $("#networks").width();
227     var topoWidth = $("#topo").width();
228     var bodyWidth = $("body").width();
229     (networkWidth+topoWidth+50) > bodyWidth ? $("body").width(networkWidth+topoWidth+topoUtil.svgOffsetWidth+10) : $("body").width($("html").width());
230
231     var containerHeight=$(".container-fluid").height();
232     $(".coordinates").height(containerHeight).width($("body").width());
233 }
234
235 /**
236  * get the widest VDU or VNF node to generate connect lines
237  * @return {[type]} [description]
238  */
239 topoUtil.getMaxNodeRight = function() {
240         var maxNode = {offsetWidth : 0};
241         for(var i=0;i<topoUtil.topoDatas.length;i++) {
242                 var node = document.getElementById(topoUtil.topoDatas[i].id);
243                 if(node && (maxNode.offsetWidth < node.offsetWidth)) {
244                         maxNode = node;
245                 }
246         }
247         return topoUtil.pageX(maxNode) + maxNode.offsetWidth;
248 }
249
250 topoUtil.initWindowEvent = function() {
251         $(window.frameElement).attr('scrolling', 'auto');
252         $('body').css('overflow', 'scroll');
253         $(window).scroll(function(){
254                 $("#right-menu").css("top",$(window).scrollTop()); //vertical scroll
255                 $("#right-menu").css("right",-1*$(window).scrollLeft()); //horizontal scroll
256         }).unload(function(){
257                 $(window.frameElement).attr('scrolling', 'no');
258         });
259         //$(window).resize(topoUtil.generateLine);
260 }
261
262 /**
263  * generate topology attachment
264  * connectedto represent the connection between the VNFC and VNFC, virtuallinksto represent the connection between the VLAN and VDU
265  * @return {[type]} [description]
266  */
267 topoUtil.generateLine = function() { 
268         topoUtil.initElementSize();
269         var vduPath='';
270         var vlPath='';
271         var vduIndex=0;
272         var vlIndex=0;
273         var fromNodeArray = [];
274         var horizontalIndex = 0;
275         var maxNodeParentRight = topoUtil.getMaxNodeRight();
276         for(var i=0;i<topoUtil.topoDatas.length;i++) {
277                 //connectedto
278                 if(topoUtil.topoDatas[i].connectedto !=""){                     
279                         var fromNode = document.getElementById(topoUtil.topoDatas[i].id); 
280                         var horizontalOffset = 0;
281                         for(var k=0;k<fromNodeArray.length;k++) {
282                                 //VNFC node in the same VDU, coordinate offset
283                                 var nodeTop = topoUtil.pageY(fromNodeArray[k]);
284                                 var fromTop = topoUtil.pageY(fromNode);
285                                 if(fromTop == nodeTop) {
286                                         horizontalOffset = topoUtil.getLineOffset(++horizontalIndex);
287                                 }
288                         }
289                         fromNodeArray.push(fromNode);                   
290                         var fromNodeParent = topoUtil.getParentNode(fromNode);
291                         var toArray = topoUtil.topoDatas[i].connectedto.split(",");                     
292                         for (var j=0;j<toArray.length;j++) {                            
293                                 var toNode = document.getElementById(toArray[j]); 
294                                 var toNodeParent = topoUtil.getParentNode(toNode);
295                                 //Computing connection point and the connection point Y coordinate offset
296                                 var fromNodeOffset = topoUtil.getNodeOffset(topoUtil.topoDatas[i], fromNode.clientHeight); 
297                                 var toNodeTopoData = topoUtil.getTopoDataById(toArray[j]);
298                                 var toNodeOffset = topoUtil.getNodeOffset(toNodeTopoData, toNode.clientHeight); 
299                                 //X coordinate offset calculation link
300                                 var xLineOffset = topoUtil.getLineOffset(++vduIndex); 
301                                 //Get the largest X coordinate offset is used to set the width of the body
302                                 topoUtil.svgOffsetWidth = Math.max(xLineOffset, topoUtil.svgOffsetWidth);
303                                                                 
304                                 var fromNodeLeft = topoUtil.pageX(fromNode);                            
305                                 var fromNodeRight = topoUtil.pageX(fromNode) + fromNode.offsetWidth;
306                                 var fromNodeTop = topoUtil.pageY(fromNode);
307
308                                 var toNodeLeft = topoUtil.pageX(toNode);
309                                 var toNodeRight = topoUtil.pageX(toNode) + toNode.offsetWidth;
310                                 var toNodeTop = topoUtil.pageY(toNode);                         
311
312                                 var coord = '';
313                                 if(fromNodeTop == toNodeTop) {
314                                         if(fromNodeLeft < toNodeLeft) {
315                                                 coord = "M"+fromNodeRight+","+(fromNodeTop+horizontalOffset+fromNodeOffset)
316                                                         +" L"+toNodeLeft+","+(fromNodeTop+horizontalOffset+fromNodeOffset)
317                                         } else {
318                                                 coord = "M"+fromNodeLeft+","+(fromNodeTop+horizontalOffset+fromNodeOffset)                                                      
319                                                         +" L"+toNodeRight+","+(fromNodeTop+horizontalOffset+fromNodeOffset);
320                                         }
321                                 } else {
322                                         var nodeRight = maxNodeParentRight + xLineOffset;
323                                         coord = "M"+fromNodeRight+","+(fromNodeTop+horizontalOffset+fromNodeOffset)
324                                                         +" L"+nodeRight+","+(fromNodeTop+horizontalOffset+fromNodeOffset)
325                                                         +" L"+nodeRight+","+(toNodeTop+toNodeOffset)
326                                                         +" L"+toNodeRight+","+(toNodeTop+toNodeOffset);                         
327                                 }
328                                 vduPath +='<path d="'+coord+'" marker-end="url(#arrowhead)" fill="none" stroke-dasharray="5,5" stroke="#7A7A7A" stroke-width="3px" shape-rendering="geometricPrecision"></path>';       
329                         }
330                 }
331
332                 //virtuallinksto                
333                 if(topoUtil.topoDatas[i].virtuallinksto !=""){
334                         var fromNode = document.getElementById(topoUtil.topoDatas[i].id); 
335                         var toArray = topoUtil.topoDatas[i].virtuallinksto.split(",");                  
336                         for (var j=0;j<toArray.length;j++) {
337                                 var toNode = document.getElementById(toArray[j]);
338                                 if(toNode) {
339                                         var yLineOffset = topoUtil.getLineOffset(j); 
340                                         var xLineOffset = topoUtil.getLineOffset(++vlIndex); 
341
342                                         var fromNodeLeft = topoUtil.pageX(fromNode);
343                                         var fromNodeTop = topoUtil.pageY(fromNode);
344
345                                         var toNodeRight = topoUtil.pageX(toNode) + toNode.offsetWidth;
346                                         var toNodeTop = topoUtil.pageY(toNode);
347
348                                         var coord = "";
349                                         if(fromNodeTop == toNodeTop) {
350                                                 coord = "M"+fromNodeLeft+","+(fromNodeTop+fromNode.clientHeight/2+xLineOffset)
351                                                         +" L"+toNodeRight+","+(fromNodeTop+fromNode.clientHeight/2+xLineOffset);
352                                         } else {
353                                                 coord = "M"+fromNodeLeft+","+(fromNodeTop+fromNode.clientHeight/2+yLineOffset)
354                                                         +" L"+toNodeRight+","+(fromNodeTop+fromNode.clientHeight/2+yLineOffset);
355                                         }
356                                         vlPath +='<path d="'+coord+'" fill="none" stroke="'+toNode.style.backgroundColor+'" stroke-width="4px"></path>';
357                                 }                                       
358                         }
359                 }
360         }
361         
362         $("#svg_vdu g").html(vduPath);
363         $("#svg_vl g").html(vlPath);
364 }
365
366 /**
367  * generate node table data
368  * @param  {[type]} data [description]
369  * @return {[type]}      [description]
370  */
371 topoUtil.generateNodeTemplate = function(data) {
372         var nodeTemplate = {};
373         nodeTemplate.id = data.id;
374         nodeTemplate.name = data.name;
375         nodeTemplate.type = data.type;
376         nodeTemplate.parentType = data.parentType;
377         nodeTemplate.vnfdid = ""; //only nested VNF node has value
378         nodeTemplate.properties = data.properties;
379         nodeTemplate.flavors = data.flavors;     
380         nodeTemplate.containIn = ""; //containIn relation which the front-end custom is used to display the topo relations of the graph
381         nodeTemplate.containedin = ""; //the relation between VNF and VNFC
382         nodeTemplate.deployedon = ""; //the relation between VDU and VNFC
383         nodeTemplate.connectedto = ""; //the relation between VNFC and VNFC
384         nodeTemplate.virtuallinksto = ""; //the relation between VL and CP or between VL and VDU
385         nodeTemplate.virtualbindsto = ""; //the relation between CP and VDU
386         nodeTemplate.outLinks = []; //a collection of connected nodes connectedto
387         nodeTemplate.inLinks = []; //nodes are connected connectedto relationship collection
388         nodeTemplate.currentLinkNum = 0;
389         var relationShips = data.relationShips || []; //some nodes may not have relationships
390         $.each(relationShips, function(index, obj){
391                 if (obj.sourceNodeId == data.name) {
392                         switch(obj.type) {
393                                 case "containedIn" :
394                                 case "tosca.relationships.nfv.ContainedIn" :
395                                 case "tosca.relationships.nfv.BelongTo" :
396                                         nodeTemplate.containedin = obj.targetNodeId;
397                                         break;
398                                 case "deployedOn" :
399                                 case "tosca.relationships.nfv.DeployedOn" :
400                                         nodeTemplate.deployedon = obj.targetNodeId;
401                                         break;
402                                 case "connectedTo" : 
403                                 case "tosca.relationships.nfv.ConnectsTo" :
404                                         nodeTemplate.connectedto += "," + obj.targetNodeId;
405                                         nodeTemplate.outLinks.push(obj.targetNodeId);
406                                         break;
407                                 case "virtualLinksTo" :
408                                 case "tosca.relationships.nfv.VirtualLinksTo" :
409                                         nodeTemplate.virtuallinksto += "," + obj.targetNodeId;
410                                         break;
411                                 case "virtualBindsTo" :
412                                 case "tosca.relationships.nfv.VirtualBindsTo" :
413                                         nodeTemplate.virtualbindsto += "," + obj.targetNodeId;
414                                         break;
415                         }
416                 }
417                 if (obj.targetNodeId == data.name) {
418                         switch(obj.type) {
419                                 case "connectedTo" : 
420                                 case "tosca.relationships.nfv.ConnectsTo" :
421                                         nodeTemplate.inLinks.push(obj.sourceNodeId);
422                                         break;
423                         }
424                 }
425         });
426         nodeTemplate.connectedto = nodeTemplate.connectedto.substring(1);
427         nodeTemplate.virtuallinksto = nodeTemplate.virtuallinksto.substring(1);
428         nodeTemplate.virtualbindsto = nodeTemplate.virtualbindsto.substring(1);
429
430         if(topoUtil.isVNFType(data.type)) {
431         $.each(data.properties, function(key, value) {
432             if(key == "vnfdid" && value) {
433                 nodeTemplate.vnfdid = value;
434             }
435         });
436         }
437         return nodeTemplate;
438 }
439
440 /**
441  * generate topology data
442  * deployedon is used to display the relation between VNFC and VDU
443  * containedin is used to display the relation between VNFC and VNF
444  * transform relations between VDU and VNF, containIn is used to display the relation between VDU and VNF
445  * @param  {[type]} data [description]
446  * @return {[type]}      [description]
447  */
448 topoUtil.generateTopoTemplate = function(data) {
449         for(var i=0;i<data.length;i++) {
450                 if(data[i].containedin){
451                         //assignment is designed to compatible with no VDU, only VNF and VNFC situations
452                         data[i].containIn = data[i].containedin;
453                         for(var j=0;j<data.length;j++) {
454                                 if(data[i].deployedon == data[j].id) {
455                                         data[j].containIn = data[i].containedin;
456                                         break;
457                                 }
458                         }
459                 }
460                 //the relationship between VNFC and VDU deployedon replace with containIn
461                 if(data[i].deployedon){
462                         data[i].containIn = data[i].deployedon;
463                 }
464         }
465         return data;    
466 }
467
468 /**
469  * generate nodetemplate detail
470  * @param  {[type]} data [description]
471  * @return {[type]}      [description]
472  */
473 topoUtil.generateNodeTemplateDetail = function(data) {
474         var nodeTemplateDetail = {};
475         nodeTemplateDetail.properties = [];
476         var properties = data.properties;
477         for(var key in properties) {
478                 var property = {};
479                 property.key = key;
480                 property.value = properties[key];
481                 nodeTemplateDetail.properties.push(property);
482         }
483         //add flavor to nodetempalte properties
484         var flavors = data.flavors;
485         if(flavors && flavors.length) {
486                 var flavor = flavors[0];
487                 for(var key in flavor) {
488                         var property = {};
489                         property.key = key;
490                         property.value = flavor[key];
491                         nodeTemplateDetail.properties.push(property);
492                 }
493         }
494
495         nodeTemplateDetail.relationShips = data.relationShips;  
496
497         nodeTemplateDetail.general = [];
498         var general = {};
499         general.key = "name";
500         general.value = data.name;
501         nodeTemplateDetail.general.push(general);
502         var general = {};
503         general.key = "type";
504         general.value = data.type;
505         nodeTemplateDetail.general.push(general);
506
507         return nodeTemplateDetail;
508 }
509
510 topoUtil.getCurrentDetailData = function(detailDatas, nodetemplateid) {
511     var data;
512     for(var i=0; i<detailDatas.length; i++) {
513         if (detailDatas[i].id == nodetemplateid) {
514             data = topoUtil.generateNodeTemplateDetail(detailDatas[i]);
515             break;
516         }
517     }
518     return data;
519 }
520
521 /**
522  * generate node instance detail
523  * a node template may correspond to multiple node instances, their properties are not the same
524  * @param  {[type]} data [description]
525  * @return {[type]}      [description]
526  */
527 topoUtil.generateNodeInstanceDetail = function(data) {
528         var nodeInstanceDetail = [];
529         nodeInstanceDetail.properties = [];
530         nodeInstanceDetail.general = [];        
531
532         var properties = data.properties;
533         for(var i=0;i<properties.length;i++) {
534                 var nodeDetail = {};
535                 var name = data.name;           
536                 for(var key in properties[i]) {
537                         var property = {};
538                         property.key = key;
539                         property.value = properties[i][key];                    
540                         nodeDetail.properties.push(property);
541
542                         if(key == "name") {
543                                 name = properties[i][key];
544                         }
545                 }
546                 var general = {};
547                 general.key = "name";
548                 general.value = name;
549                 nodeDetail.general.push(general);
550                 var general = {};
551                 general.key = "type";
552                 general.value = data.type;
553                 nodeDetail.general.push(general);
554
555                 nodeDetail.relationShips = data.relationShips;
556                 nodeInstanceDetail.push(nodeDetail);
557         }
558         return nodeInstanceDetail;
559 }
560
561 topoUtil.getCurrentNodeInstanceDetail = function(detailDatas, nodetemplateid) {
562     var data;
563     for(var i=0; i<detailDatas.length; i++) {
564         if (detailDatas[i].id == nodetemplateid) {
565             data = topoUtil.generateNodeInstanceDetail(detailDatas[i]);
566             break;
567         }
568     }
569     return data;
570 }
571
572 topoUtil.getCidr = function(properties) {
573         for(var key in properties) {
574         if(key == "cidr") {
575                 return properties[key];
576         }
577     }
578 }
579
580 topoUtil.getColor = function(index) {
581         var colors = ['#1F77B4','#FF7F0E','#2CA02C','#D62728','#9467BD','#8C564B','#4b6c8b','#550000','#dc322f','#FF6600'];
582         return colors[index%10];
583 }
584
585 topoUtil.getCpTop = function(index, parentBoxId) {
586     var newTop = "";
587     var height = 0;
588     if(index == 0) {
589         var circle_top = $(".circle").css("top");
590         var circle_height = $(".circle").css("height");
591         var top = circle_top.substring(0, circle_top.length-2) - 0;
592         height = circle_height.substring(0, circle_height.length-2) - 0;
593         newTop = (top+height+10);
594     } else {
595         var circle_top = $(".smallCircle").css("top");
596         var circle_height = $(".smallCircle").css("height");
597         var top = circle_top.substring(0, circle_top.length-2) - 0;
598         height = circle_height.substring(0, circle_height.length-2) - 0;
599         newTop = (top+height*(index));
600     }
601     //if the length of cp over the box which cp is virtualbindsto, set the box min-heght attribute
602     var $box = $("#" + parentBoxId);
603         var min_height = $box.css("min-height");
604         var box_min_height = min_height.substring(0, min_height.length-2) - 0;
605         var cp_height = newTop + height;
606         if(cp_height > box_min_height) {
607                 $box.css("min-height", cp_height);
608         }
609
610     return newTop + "px";
611 }
612
613 topoUtil.isVNFType = function(type) {
614         if((type.toUpperCase().indexOf(".VNF") > -1) && (type.toUpperCase().indexOf(".VNFC") < 0)) {
615                 return true;
616         }
617         return false;
618 }