blob: 5521bbffc08a64fb88f25450bbc4bf3b6752510b [file] [log] [blame]
"use strict";angular.module("xos.serviceTopology",["ngResource","ngCookies","ngLodash","ngAnimate","ui.router","xos.helpers"]).config(["$stateProvider",function(e){e.state("home",{url:"/",template:"<diagnostic></diagnostic>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]),angular.module("xos.serviceTopology").run(["$templateCache",function(e){e.put("templates/diagnostic.tpl.html",'<div class="container-fluid">\n <div ng-hide="vm.error && vm.loader">\n <div class="onethird-height">\n <service-topology service-chain="vm.serviceChain"></service-topology>\n </div>\n <div class="twothird-height">\n <!-- <div class="panel panel-primary subscriber-select">\n <div class="panel-heading">Select a subscriber:</div>\n <div class="panel-body">\n <select class="form-control" ng-options="s as s.name for s in vm.subscribers" ng-model="vm.selectedSubscriber">\n <option value="">Select a subscriber...</option>\n </select>\n </div>\n </div> -->\n <logic-topology ng-if="vm.subscribers" subscribers="vm.subscribers" selected="vm.selectedSubscriber"></logic-topology>\n </div>\n </div>\n <div class="row" ng-show="vm.error">\n <div class="col-xs-12">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n </div>\n </div>\n <div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n </div>\n</div>'),e.put("templates/logicTopology.tpl.html",'<subscriber-modal open="vm.subscriberModal" subscribers="vm.subscribers"></subscriber-modal>\n<div class="instances-stats animate" ng-hide="vm.hideInstanceStats">\n <div class="row">\n <div class="col-sm-3 col-sm-offset-8">\n <div class="panel panel-primary" ng-repeat="instance in vm.selectedInstances">\n <div class="panel-heading">\n {{instance.humanReadableName}}\n </div>\n <ul class="list-group">\n <li class="list-group-item">Backend Status: {{instance.backend_status}}</li>\n <li class="list-group-item">IP Address: {{instance.ip}}</li>\n </ul>\n <ul class="list-group">\n <li class="list-group-item" ng-repeat="stat in instance.stats">\n <span class="badge">{{stat.value}}</span>\n {{stat.meter}}\n </li>\n </ul>\n </div>\n </div> \n </div>\n </div>\n</div>'),e.put("templates/subscriber-modal.tpl.html",'<div class="modal fade" ng-class="{in: vm.open}" tabindex="-1" role="dialog">\n <div class="modal-dialog modal-sm">\n <div class="modal-content">\n <div class="modal-header">\n <button ng-click="vm.close()" type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>\n <h4 class="modal-title">Select a subscriber:</h4>\n </div>\n <div class="modal-body">\n <select class="form-control" ng-options="s as s.humanReadableName for s in vm.subscribers" ng-model="vm.selected"></select>\n </div>\n <div class="modal-footer">\n <button ng-click="vm.close()" type="button" class="btn btn-default" data-dismiss="modal">Close</button>\n <button ng-click="vm.select(vm.selected)" type="button" class="btn btn-primary">Select</button>\n </div>\n </div><!-- /.modal-content -->\n </div><!-- /.modal-dialog -->\n</div><!-- /.modal -->')}]),angular.module("xos.serviceTopology").run(["$location",function(e){e.path("/")}]),angular.bootstrap(angular.element("#xosServiceTopology"),["xos.serviceTopology"]),function(){angular.module("xos.serviceTopology").directive("subscriberModal",function(){return{scope:{subscribers:"=",open:"="},bindToController:!0,restrict:"E",templateUrl:"templates/subscriber-modal.tpl.html",controllerAs:"vm",controller:["$rootScope",function(e){var t=this;this.close=function(){t.open=!1},this.select=function(n){e.$emit("subscriber.selected",n),t.close()}}]}})}(),function(){angular.module("xos.serviceTopology").service("ServiceTopologyHelper",["$rootScope","$window","$log","lodash","ServiceRelation","serviceTopologyConfig","d3",function(e,t,n,r,i,a,o){var c,s,u,l=function(e){var t=e.append("g").attr({"class":"legend"});t.append("rect").attr({transform:function(e){return"translate(10, 80)"},width:100,height:100});var n=t.append("g").attr({"class":"node service"});n.append("circle").attr({r:a.circle.radius,transform:function(e){return"translate(30, 100)"}}),n.append("text").attr({transform:function(e){return"translate(45, 100)"},dy:".35em"}).text("Service").style("fill-opacity",1);var r=t.append("g").attr({"class":"node slice"});r.append("rect").attr({width:20,height:20,x:-10,y:-10,transform:function(e){return"translate(30, 130)"}}),r.append("text").attr({transform:function(e){return"translate(45, 130)"},dy:".35em"}).text("Slices").style("fill-opacity",1);var i=t.append("g").attr({"class":"node instance"});i.append("rect").attr({width:20,height:20,x:-10,y:-10,transform:function(e){return"translate(30, 160)"}}),i.append("text").attr({transform:function(e){return"translate(45, 160)"},dy:".35em"}).text("Instances").style("fill-opacity",1)},d=0,p=function(e,n,r){c=e,s=n,u=r;var l=i.depthOf(r),p=o.svg.diagonal().projection(function(e){return[e.y,e.x]}),f=n.nodes(r).reverse(),g=n.links(f);f.forEach(function(e){var n=(t.innerWidth-2*a.widthMargin)/l;e.y=e.depth*n});var v=e.selectAll("g.node").data(f,function(e){return e.id||(e.id=++d)}),m=v.enter().append("g").attr({"class":function(e){return"node "+e.type},transform:function(e){return e.x&&e.y?"translate("+e.y+", "+e.x+")":"translate("+r.y0+", "+r.x0+")"}}),b=m.filter(".subscriber"),y=m.filter(".router"),x=m.filter(".service");b.append("rect").attr(a.square),y.append("rect").attr(a.square),x.append("circle").attr("r",1e-6).style("fill",function(e){return e._children?"lightsteelblue":"#fff"}).on("click",h),m.append("text").attr({x:function(e){return e.children?-a.circle.selectedRadius-3:a.circle.selectedRadius+3},dy:".35em",transform:function(e){return e.children&&e.parent?e.parent.x<e.x?"rotate(-30)":"rotate(30)":void 0},"text-anchor":function(e){return e.children?"end":"start"}}).text(function(e){return e.name}).style("fill-opacity",1e-6);var S=v.transition().duration(a.duration).attr({transform:function(e){return"translate("+e.y+","+e.x+")"}});S.select("circle").attr("r",function(e){return e.selected?a.circle.selectedRadius:a.circle.radius}).style("fill",function(e){return e.selected?"lightsteelblue":"#fff"}),S.select("text").style("fill-opacity",1);var T=v.exit().transition().duration(a.duration).remove();T.select("circle").attr("r",1e-6),T.select("text").style("fill-opacity",1e-6);var w=e.selectAll("path.link").data(g,function(e){return e.target.id});w.enter().insert("path","g").attr("class",function(e){return"link "+e.target.type+" "+(e.target.active?"":"active")}).attr("d",function(e){var t={x:r.x0,y:r.y0};return p({source:t,target:t})}),w.transition().duration(a.duration).attr("d",p),w.exit().transition().duration(a.duration).attr("d",function(e){var t={x:r.x,y:r.y};return p({source:t,target:t})}).remove(),f.forEach(function(e){e.x0=e.x,e.y0=e.y})},h=function(t){return t.selected?(t.selected=!t.selected,e.$emit("instance.detail.hide",{}),p(c,s,u)):(e.$emit("instance.detail",{name:t.name,service:t.service,tenant:t.tenant}),c.selectAll("circle").each(function(e){return e.selected=!1}),t.selected=!t.selected,void p(c,s,u))};this.updateTree=p,this.drawLegend=l}])}(),function(){angular.module("xos.serviceTopology").directive("serviceTopology",function(){return{restrict:"E",scope:{serviceChain:"="},bindToController:!0,controllerAs:"vm",template:"",controller:["$element","$window","$scope","d3","serviceTopologyConfig","ServiceRelation","Slice","Instances","Subscribers","ServiceTopologyHelper",function(e,t,n,r,i,a,o,c,s,u){var l=this,d=e[0];r.select(window).on("resize",function(){f(l.serviceChain)});var p,h,f=function(t){r.select(e[0]).select("svg").remove();var n=d.clientWidth-2*i.widthMargin,a=d.clientHeight-2*i.heightMargin,o=r.layout.tree().size([a,n]);h=r.select(e[0]).append("svg").style("width",d.clientWidth+"px").style("height",d.clientHeight+"px");var c=h.append("g").attr("transform","translate("+4*i.widthMargin+","+i.heightMargin+")");p=t,p.x0=a/2,p.y0=n/2,u.updateTree(c,o,p)};this.getInstances=function(e){c.query({slice:e.id}).$promise.then(function(t){l.selectedSlice=e,l.instances=t})["catch"](function(e){throw l.errors=e,new Error(e)})},n.$watch(function(){return l.serviceChain},function(e){e&&f(e)})}]}})}(),function(){angular.module("xos.serviceTopology").service("Services",["$resource",function(e){return e("/xos/services/:id",{id:"@id"})}]).service("Tenant",["$resource",function(e){return e("/xos/tenants",{id:"@id"},{queryVsgInstances:{method:"GET",isArray:!0,interceptor:{response:function(e){var t=[];return angular.forEach(e.data,function(e){var n=JSON.parse(e.service_specific_attribute);n&&n.instance_id&&t.push(n.instance_id)}),t}}},getSubscriberTag:{method:"GET",isArray:!0,interceptor:{response:function(e){return JSON.parse(e.data[0].service_specific_attribute)}}}})}]).service("Ceilometer",["$http","$q","Instances",function(e,t,n){var r=this;this.getInstanceStats=function(n){var r=t.defer();return e.get("/xoslib/xos-instance-statistics",{params:{"instance-uuid":n}}).then(function(e){r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getInstancesStats=function(e){var i=t.defer(),a=[],o=[];return e.forEach(function(e){a.push(n.get({id:e}).$promise)}),t.all(a).then(function(e){o=e;var n=[];return o.forEach(function(e){n.push(r.getInstanceStats(e.instance_uuid))}),t.all(n)}).then(function(e){o.map(function(t,n){t.stats=e[n]}),i.resolve(o)})["catch"](i.reject),i.promise},this.getContainerStats=function(n){var r=t.defer(),i={};return e.get("/xoslib/meterstatistics",{params:{resource:n}}).then(function(t){return i.stats=t.data,e.get("/xoslib/meterstatistics",{params:{resource:n+"-eth0"}})}).then(function(t){return i.port={eth0:t.data},e.get("/xoslib/meterstatistics",{params:{resource:n+"-eth1"}})}).then(function(e){i.port.eth1=e.data,r.resolve(i)})["catch"](function(e){r.reject(e)}),r.promise}}]).service("Slice",["$resource",function(e){return e("/xos/slices",{id:"@id"})}]).service("Instances",["$resource",function(e){return e("/xos/instances/:id",{id:"@id"})}]).service("Node",["$resource","$q","Instances",function(e,t,n){return e("/xos/nodes",{id:"@id"},{queryWithInstances:{method:"GET",isArray:!0,interceptor:{response:function(e){var r=t.defer(),i=[];return angular.forEach(e.data,function(e){i.push(n.query({node:e.id}).$promise)}),t.all(i).then(function(t){e.data.map(function(e,n){return e.instances=t[n],e}),r.resolve(e.data)}),r.promise}}}})}]).service("Subscribers",["$resource","$q","SubscriberDevice",function(e,t,n){return e("/xos/subscribers/:id",{id:"@id"},{queryWithDevices:{method:"GET",isArray:!0,interceptor:{response:function(e){var r=t.defer(),i=[];return angular.forEach(e.data,function(e){i.push(n.query({id:e.id}).$promise)}),t.all(i).then(function(t){e.data.map(function(e,n){return e.devices=t[n],e.type="subscriber",e.devices.map(function(e){return e.type="device"}),e}),r.resolve(e.data)}),r.promise}}},getWithDevices:{method:"GET",isArray:!1,interceptor:{response:function(e){var r=t.defer();return n.query({id:e.data.id}).$promise.then(function(t){t.map(function(e){return e.type="device"}),e.data.devices=t,e.data.type="subscriber",r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise}}}})}]).service("SubscriberDevice",["$resource",function(e){return e("/xoslib/rs/subscriber/:id/users/",{id:"@id"})}]).service("ServiceRelation",["$q","lodash","Services","Tenant","Slice","Instances",function(e,t,n,r,i,a){var o=function g(e){var t=0;return e.children&&e.children.forEach(function(e){var n=g(e);n>t&&(t=n)}),1+t},c=function(e,n){return t.filter(e,function(e){return e.subscriber_service===n})},s=function(e,n){var r,e=t.filter(e,function(e){return e.provider_service===n&&e.subscriber_tenant});return e.forEach(function(e){e.service_specific_attribute&&(r=JSON.parse(e.service_specific_attribute))}),r},u=function(e,n){var r=[];return t.forEach(e,function(e){var i=t.find(n,{id:e.provider_service});r.push(i)}),r},l=function v(e,n,r,i){var a=arguments.length<=4||void 0===arguments[4]?null:arguments[4],o=t.difference(n,[r]),l=c(e,r.id),d=u(l,n);o=t.difference(o,d),r.service_specific_attribute=s(e,r.id);var p={name:r.humanReadableName,parent:a,type:"service",service:r,tenant:i,children:[]};return t.forEach(d,function(n){var a=t.find(e,{subscriber_tenant:i.id,provider_service:n.id});p.children.push(v(e,o,n,a,r.humanReadableName))}),0===p.children.length&&p.children.push({name:"Router",type:"router",children:[]}),p},d=function(e,n){var r=arguments.length<=2||void 0===arguments[2]?{id:1,name:"fakeSubs"}:arguments[2],i=t.find(n,{subscriber_root:r.id}),a=t.find(e,{id:i.provider_service}),o=l(n,e,a,i);return{name:r.name,parent:null,type:"subscriber",children:[o]}},p=function(e,n){var r=function o(e,n,r){var i={type:"service",name:r.humanReadableName,service:r},a=t.find(n,{subscriber_service:r.id});if(a){var c=t.find(e,{id:a.provider_service});i.children=[o(e,n,c)]}else i.children=[{name:"Router",type:"router",children:[]}];return delete r.id,i},i=t.find(e,{id:3}),a={name:"Subscriber",type:"subscriber",parent:null,children:[r(e,n,i)]};return a},h=function(t){var i,a,o=e.defer();return n.query().$promise.then(function(e){return i=e,r.query().$promise}).then(function(e){a=e,o.resolve(d(i,a,t))})["catch"](function(e){throw new Error(e)}),o.promise},f=function(){var t,i,a=e.defer();return n.query().$promise.then(function(e){return t=e,r.query({kind:"coarse"}).$promise}).then(function(e){i=e,a.resolve(p(t,i))})["catch"](function(e){throw new Error(e)}),a.promise};return{get:f,buildServiceTree:p,getBySubscriber:h,buildLevel:l,buildSubscriberServiceTree:d,findLevelRelation:c,findLevelServices:u,depthOf:o,findSpecificInformation:s}}])}();var _slicedToArray=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o,c=e[Symbol.iterator]();!(r=(o=c.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(s){i=!0,a=s}finally{try{!r&&c["return"]&&c["return"]()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();!function(){angular.module("xos.serviceTopology").service("RackHelper",["serviceTopologyConfig","lodash",function(e,t){var n=this;this.getComputeNodeLabelSize=function(){return e.computeNode.labelHeight+2*e.instance.margin},this.getComputeNodeSize=t.memoize(function(t){var r=3*e.instance.margin+2*e.instance.width,i=Math.round(t.length/2),a=n.getComputeNodeLabelSize(),o=e.instance.height*i+e.instance.margin*(i+1)+a;return[r,o]}),this.getRackSize=function(r){var i=0,a=e.computeNode.margin;return t.forEach(r,function(t){var r=n.getComputeNodeSize(t.instances),o=_slicedToArray(r,2),c=o[0],s=o[1];i=c+2*e.computeNode.margin,a+=s+e.computeNode.margin}),[i,a]},this.getInstancePosition=function(t){var r=Math.floor(t/2),i=t%2?1:0,a=n.getComputeNodeLabelSize(),o=e.instance.margin+e.instance.width*i+e.instance.margin*i,c=a+e.instance.margin+e.instance.height*r+e.instance.margin*r;return[o,c]},this.getComputeNodePosition=function(r,i){var a=e.computeNode.margin,o=t.reduce(r.slice(0,i),function(e,t){return e+n.getComputeNodeSize(t.instances)[1]},0),c=e.computeNode.margin+e.computeNode.margin*i+o;return[a,c]}}])}();var _slicedToArray=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o,c=e[Symbol.iterator]();!(r=(o=c.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(s){i=!0,a=s}finally{try{!r&&c["return"]&&c["return"]()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();!function(){var e={cloud:" M 79.72 49.60 C 86.00 37.29 98.57 29.01 111.96 26.42 C 124.27 24.11 137.53 26.15 148.18 32.90 C 158.08 38.78 165.39 48.87 167.65 60.20 C 176.20 57.90 185.14 56.01 194.00 57.73 C 206.08 59.59 217.92 66.01 224.37 76.66 C 227.51 81.54 228.85 87.33 229.23 93.06 C 237.59 93.33 246.22 95.10 253.04 100.19 C 256.69 103.13 259.87 107.67 258.91 112.59 C 257.95 118.43 252.78 122.38 247.78 124.82 C 235.27 130.43 220.23 130.09 207.98 123.93 C 199.33 127.88 189.76 129.43 180.30 128.57 C 173.70 139.92 161.70 147.65 148.86 149.93 C 133.10 153.26 116.06 148.15 104.42 137.08 C 92.98 143.04 78.96 143.87 66.97 139.04 C 57.75 135.41 49.70 128.00 46.60 118.43 C 43.87 109.95 45.81 100.29 51.30 93.32 C 57.38 85.18 67.10 80.44 76.99 78.89 C 74.38 69.20 74.87 58.52 79.72 49.60 Z"},t=0,n=0;angular.module("xos.serviceTopology").service("NodeDrawer",["d3","serviceTopologyConfig","RackHelper","lodash",function(r,i,a,o){var c=this,s=this;this.addNetworks=function(t){t.append("path").attr({d:e.cloud,transform:"translate(-63, -52), scale(0.5)","class":"cloud"}),t.append("text").attr({"text-anchor":"middle"}).text(function(e){return e.name}),t.each(function(e){var t=r.select(this);"LAN"===e.name&&angular.isDefined(e.subscriberTag)&&(t.append("text").attr({"text-anchor":"middle",y:40}).text(function(){return"C-Tag: "+e.subscriberTag.cTag}),t.append("text").attr({"text-anchor":"middle",y:60}).text(function(){return"S-Tag: "+e.subscriberTag.sTag})),"WAN"===e.name&&angular.isDefined(e.subscriberIP)&&t.append("text").attr({"text-anchor":"middle",y:40}).text(function(){return"Public IP: "+e.subscriberIP})})},this.addRack=function(e){e.each(function(t){var n=a.getRackSize(t.computeNodes),r=_slicedToArray(n,2),o=r[0],s=r[1];e.select("g").remove();var u=e.append("g");u.attr({transform:"translate(0,0)"}).transition().duration(i.duration).attr({transform:function(){return"translate("+-(o/2)+", "+-(s/2)+")"}}),u.append("rect").attr({width:0,height:0}).transition().duration(i.duration).attr({width:o,height:s}),u.append("text").attr({"text-anchor":"middle",y:-10,x:o/2,opacity:0}).text(function(e){return e.name}).transition().duration(i.duration).attr({opacity:1}),c.drawComputeNodes(u,t.computeNodes)})},this.drawComputeNodes=function(e,n){var o=e.selectAll(".compute-nodes").data(n,function(e){return angular.isString(e.d3Id)||(e.d3Id="compute-node-"+ ++t),e.d3Id}),c=e.node().getBoundingClientRect(),u=c.width,l=c.height,d=o.enter().append("g");d.attr({transform:"translate("+u/2+", "+l/2+")","class":"compute-node"}).transition().duration(i.duration).attr({transform:function(e){return"translate("+a.getComputeNodePosition(n,e.d3Id.replace("compute-node-","")-1)+")"}}),d.append("rect").attr({width:0,height:0}).transition().duration(i.duration).attr({width:function(e){return a.getComputeNodeSize(e.instances)[0]},height:function(e){return a.getComputeNodeSize(e.instances)[1]}}),d.append("text").attr({"text-anchor":"start",y:15,x:10,opacity:0}).text(function(e){return e.humanReadableName.split(".")[0]}).transition().duration(i.duration).attr({opacity:1}),d.length>0&&d.each(function(e){s.drawInstances(r.select(this),e.instances)})};var u=function(e){return e.replace("app_","").replace("service_","").replace("mysite_","").replace("_instance","")},l=function(e){function t(e,t){return t.substring(0,e.length)===e}return t("0 - ",e.backend_status)?"provisioning":t("1 - ",e.backend_status)?"good":t("2 - ",e.backend_status)?"bad":""},d=function(e,t){var n=e.append("g").attr({"class":"container",transform:"translate("+i.instance.margin+", 115)"});n.append("rect").attr({width:250-2*i.container.margin,height:i.container.height}),n.append("text").attr({y:20,x:i.instance.margin,"class":"name"}).text(t.name);var r=["memory","memory.usage","cpu_util"];r.forEach(function(e,r){var a=o.find(t.stats,{meter:e});angular.isDefined(a)&&n.append("text").attr({y:40+15*r,x:i.instance.margin,opacity:0}).text(a.description+": "+Math.round(a.value)+" "+a.unit).transition().duration(i.duration).attr({opacity:1})});var a=["eth0","eth1"],c=[{meter:"network.incoming.bytes.rate",label:"Incoming"},{meter:"network.outgoing.bytes.rate",label:"Outgoing"}];a.forEach(function(e,r){0!==t.port[e].length&&(n.append("text").attr({y:90,x:i.instance.margin+120*r,"class":"name"}).text(t.name+"-"+e),c.forEach(function(a,c){var s=o.find(t.port[e],{meter:a.meter});angular.isDefined(s)&&n.append("text").attr({y:105+15*c,x:i.instance.margin+120*r,opacity:0}).text(a.label+": "+Math.round(s.value)+" "+s.unit).transition().duration(i.duration).attr({opacity:1})}))})},p=function(e,t){var n=e.append("g").attr({transform:"translate(200, -120)","class":"stats-container"});n.append("line").attr({x1:-160,y1:120,x2:0,y2:50,stroke:"black",opacity:0}).transition().duration(i.duration).attr({opacity:1});var r=110,a=250;t.container&&(r+=i.container.height+2*i.container.margin),n.append("rect").attr({width:a,height:r,opacity:0}).transition().duration(i.duration).attr({opacity:1}),n.append("text").attr({y:15,x:i.instance.margin,"class":"name",opacity:0}).text(t.humanReadableName).transition().duration(i.duration).attr({opacity:1}),n.append("text").attr({y:30,x:i.instance.margin,"class":"ip",opacity:0}).text(t.ip).transition().duration(i.duration).attr({opacity:1});var c=["memory","memory.usage","cpu","vcpus"];c.forEach(function(e,r){var a=o.find(t.stats,{meter:e});n.append("text").attr({y:55+15*r,x:i.instance.margin,opacity:0}).text(a.description+": "+Math.round(a.value)+" "+a.unit).transition().duration(i.duration).attr({opacity:1})}),t.container&&d(n,t.container)};this.drawInstances=function(e,t){var o=e.node().getBoundingClientRect(),c=o.width,s=o.height,d=e.selectAll(".instances").data(t,function(e){return angular.isString(e.d3Id)?e.d3Id:e.d3Id="instance-"+ ++n}),h=d.enter().append("g");h.attr({transform:"translate("+c/2+", "+s/2+")","class":function(e){return"instance "+(e.selected?"active":"")+" "+l(e)}}).transition().duration(i.duration).attr({transform:function(e,t){return"translate("+a.getInstancePosition(t)+")"}}),h.append("rect").attr({width:0,height:0}).transition().duration(i.duration).attr({width:i.instance.width,height:i.instance.height}),h.append("text").attr({"text-anchor":"middle",y:23,x:40,opacity:0}).text(function(e){return u(e.humanReadableName)}).transition().duration(i.duration).attr({opacity:1}),h.each(function(e,t){var n=r.select(this);angular.isDefined(e.stats)&&e.selected&&p(n,e,t)}),h.on("click",function(e){console.log("Draw vignette with stats for instance: "+e.name)})},this.addPhisical=function(e){e.append("rect").attr(i.square),e.append("text").attr({"text-anchor":"middle",y:i.square.y-10}).text(function(e){return e.name})},this.addDevice=function(e){e.append("circle").attr(i.circle),e.append("text").attr({"text-anchor":"end",x:-i.circle.r-10,y:i.circle.r/2}).text(function(e){return e.name||e.mac})}}])}();var _slicedToArray=function(){function e(e,t){var n=[],r=!0,i=!1,a=void 0;try{for(var o,c=e[Symbol.iterator]();!(r=(o=c.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(s){i=!0,a=s}finally{try{!r&&c["return"]&&c["return"]()}finally{if(i)throw a}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();!function(){angular.module("xos.serviceTopology").service("LogicTopologyHelper",["$window","$log","$rootScope","lodash","serviceTopologyConfig","NodeDrawer","ChartData",function(e,t,n,r,i,a,o){var c,s,u,l,d,p,h=this,f=0,g=o.logicTopologyData;this.computeElementPosition=function(e){var t=[],n=r.reduce(i.elWidths,function(e,t){return t+e},0),a=e-n-2*i.widthMargin,o=a/(i.elWidths.length-1);return r.forEach(i.elWidths,function(n,a){var c=0;0!==a&&(c=r.reduce(i.elWidths.slice(0,a),function(e,t){return t+e},0));var s=i.widthMargin+o*a+n/2+c;t.push(e-s)}),t};var v=function(e){var t=p.nodes(e);t.forEach(function(e){e.y=h.computeElementPosition(l)[e.depth]});var n=p.links(t);return[t,n]},m=function(e,t){var r=e.selectAll("g.node").data(t,function(e){return angular.isString(e.d3Id)||(e.d3Id="tree-"+ ++f),e.d3Id});r.enter().append("g").attr({"class":function(e){return"node "+e.type},transform:"translate("+l/2+", "+d/2+")"});a.addNetworks(r.filter(".network")),a.addRack(r.filter(".rack")),a.addPhisical(r.filter(".router")),a.addPhisical(r.filter(".subscriber")),a.addDevice(r.filter(".device")),r.filter(".subscriber").on("click",function(){n.$emit("subscriber.modal.open")});r.transition().duration(i.duration).attr({transform:function(e){return"translate("+e.y+","+e.x+")"}}),r.exit().remove()},b=function(e,t){c=d3.svg.diagonal().projection(function(e){return[e.y,e.x]});var n=e.selectAll("path.link").data(t,function(e){return e.target.d3Id});n.enter().insert("path","g").attr("class",function(e){return"link "+e.target.type}).attr("d",function(e){var t={x:d/2,y:l/2};return c({source:t,target:t})}),n.transition().duration(i.duration).attr("d",c),n.exit().remove()};this.setupTree=function(e){l=e.node().getBoundingClientRect().width,d=e.node().getBoundingClientRect().height;var t=l-2*i.widthMargin,n=d-2*i.heightMargin;p=d3.layout.tree().size([n,t])},this.updateTree=function(e){var t=v(g),n=_slicedToArray(t,2);s=n[0],u=n[1],m(e,s),b(e,u)}}])}(),function(){angular.module("xos.serviceTopology").directive("logicTopology",function(){return{restrict:"E",scope:{subscribers:"=",selected:"="},bindToController:!0,controllerAs:"vm",templateUrl:"templates/logicTopology.tpl.html",controller:["$element","$log","$scope","$rootScope","$timeout","d3","LogicTopologyHelper","Node","Tenant","Ceilometer","serviceTopologyConfig","ChartData",function(e,t,n,r,i,a,o,c,s,u,l,d){var p=this;t.info("Logic Plane");var h;this.selectedInstances=[],this.hideInstanceStats=!0;var f=function(e){h=a.select(e).append("svg").style("width",e.clientWidth+"px").style("height",e.clientHeight+"px")};d.getLogicTree().then(function(e){o.updateTree(h)}),n.$watch(function(){return p.selected},function(e){e&&(d.selectSubscriber(e),o.updateTree(h))}),r.$on("instance.detail.hide",function(){p.hideInstanceStats=!0,i(function(){p.selectedInstances=[],d.highlightInstances([]),o.updateTree(h)},500)}),r.$on("instance.detail",function(e,t){d.getInstanceStatus(t).then(function(e){o.updateTree(h)})}),f(e[0]),o.setupTree(h),this.openSubscriberModal=function(){p.subscriberModal=!0,n.$apply()},r.$on("subscriber.modal.open",function(){p.openSubscriberModal()})}]}})}(),function(){angular.module("xos.serviceTopology").directive("diagnostic",function(){return{restrict:"E",templateUrl:"templates/diagnostic.tpl.html",controllerAs:"vm",controller:["ChartData","Subscribers","ServiceRelation","$rootScope",function(e,t,n,r){var i=this;this.loader=!0,this.error=!1,t.query().$promise.then(function(e){return i.subscribers=e,n.get()}).then(function(e){i.serviceChain=e})["catch"](function(e){throw new Error(e)})["finally"](function(){i.loader=!1}),r.$on("subscriber.selected",function(r,a){n.getBySubscriber(a).then(function(n){return i.serviceChain=n,e.currentServiceChain=n,t.getWithDevices({id:a.id}).$promise}).then(function(t){i.selectedSubscriber=t,e.currentSubscriber=t})})}]}})}(),function(){angular.module("xos.serviceTopology").factory("d3",["$window",function(e){return e.d3}])}(),function(){angular.module("xos.serviceTopology").constant("serviceTopologyConfig",{widthMargin:20,heightMargin:30,duration:750,elWidths:[20,104,105,104,20],circle:{radius:10,r:10,selectedRadius:15},square:{width:20,height:20,x:-10,y:-10},rack:{width:105,height:50,x:-30,y:-25},computeNode:{width:50,height:20,margin:5,labelHeight:10,x:-25,y:-10},instance:{width:80,height:36,margin:5,x:-40,y:-18},container:{width:60,height:130,margin:5,x:-30,y:-15}})}(),function(){angular.module("xos.serviceTopology").service("ChartData",["$rootScope","$q","lodash","Tenant","Node","serviceTopologyConfig","Ceilometer","Instances",function(e,t,n,r,i,a,o,c){var s=this;this.currentSubscriber=null,this.currentServiceChain=null,this.logicTopologyData={name:"Router",type:"router",children:[{name:"WAN",type:"network",children:[{name:"Rack",type:"rack",computeNodes:[],children:[{name:"LAN",type:"network",children:[{name:"Subscriber",type:"subscriber"}]}]}]}]},this.getLogicTree=function(){var e=t.defer();return i.queryWithInstances().$promise.then(function(t){s.logicTopologyData.children[0].children[0].computeNodes=t,e.resolve(s.logicTopologyData)}),e.promise},this.addSubscriberTag=function(e){s.logicTopologyData.children[0].children[0].children[0].subscriberTag={cTag:e.c_tag,sTag:e.s_tag}},this.addSubscriber=function(e){return e.children=e.devices,s.logicTopologyData.children[0].children[0].children[0].children=[e],s.logicTopologyData},this.getSubscriberTag=function(){var e=JSON.parse(s.currentServiceChain.children[0].tenant.service_specific_attribute);delete e.creator_id,s.addSubscriberTag(e),s.currentSubscriber.tags={cTag:e.c_tag,sTag:e.s_tag}},this.getSubscriberIP=function(){var e=JSON.parse(s.currentServiceChain.children[0].children[0].tenant.service_specific_attribute).wan_container_ip;s.logicTopologyData.children[0].subscriberIP=e},this.selectSubscriber=function(e){a.elWidths.push(160),s.addSubscriber(angular.copy(e)),s.highlightInstances([]),s.getSubscriberTag(),s.getSubscriberIP()},this.highlightInstances=function(e){var t=s.logicTopologyData.children[0].children[0].computeNodes;t.map(function(e){e.instances.map(function(e){return e.selected=!1,e})}),n.forEach(e,function(e){t.map(function(t){t.instances.map(function(t){return t.id===e.id&&(t.selected=!0,t.stats=e.stats,t.container=e.container),t})})})},this.getInstanceStatus=function(e){var n=t.defer(),i=void 0;if(s.currentSubscriber){var a=void 0;try{a=JSON.parse(e.tenant.service_specific_attribute)}catch(u){a=null}if(a&&a.instance_id)!function(){var e={};i=c.get({id:a.instance_id}).$promise.then(function(t){return e=t,o.getInstanceStats(e.instance_uuid)}).then(function(t){e.stats=t;var n="vcpe-"+s.currentSubscriber.tags.sTag+"-"+s.currentSubscriber.tags.cTag;return e.container={name:n},o.getContainerStats(n)}).then(function(t){return e.container.stats=t.stats,e.container.port=t.port,[e]})}();else{var l=t.defer();l.resolve([]),i=l.promise}}else{var d={service_vsg:{kind:"vCPE"},service_vbng:{kind:"vBNG"},service_volt:{kind:"vOLT"}};i=r.queryVsgInstances(d[e.name]).$promise.then(function(e){return o.getInstancesStats(e)})}return i.then(function(e){s.highlightInstances(e),n.resolve(e)})["catch"](function(e){n.reject(e)}),n.promise}}])}();