Added Instance stats to d3 and drawing container
diff --git a/views/ngXosViews/diagnostic/src/js/chart_data_service.js b/views/ngXosViews/diagnostic/src/js/chart_data_service.js
index 4c53a03..1b0fae8 100644
--- a/views/ngXosViews/diagnostic/src/js/chart_data_service.js
+++ b/views/ngXosViews/diagnostic/src/js/chart_data_service.js
@@ -54,7 +54,7 @@
       this.logicTopologyData.children[0].children[0].children[0].subscriberTag = {
         cTag: tags.c_tag,
         sTag: tags.s_tag
-      }
+      };
     };
 
     /**
@@ -69,8 +69,15 @@
     };
 
     this.getSubscriberTag = () => {
-
-      this.addSubscriberTag(JSON.parse(this.currentServiceChain.children[0].tenant.service_specific_attribute));
+      const tags = JSON.parse(this.currentServiceChain.children[0].tenant.service_specific_attribute);
+      delete tags.creator_id;
+      
+      this.addSubscriberTag(tags);
+      // add tags info to current subscriber
+      this.currentSubscriber.tags = {
+        cTag: tags.c_tag,
+        sTag: tags.s_tag
+      };
 
     };
 
@@ -107,7 +114,10 @@
         computeNodes.map((node) => {
           node.instances.map((d3instance) => {
             if(d3instance.id === instance.id){
+              // console.log(d3instance, instance);
               d3instance.selected = true;
+              d3instance.stats = instance.stats; //add stats to d3 node
+              d3instance.container = instance.container; // container info to d3 node
             }
             return d3instance;
           });
@@ -119,18 +129,45 @@
     this.getInstanceStatus = (service) => {
       const deferred = $q.defer();
 
-      // NOTE consider if subscriber is selected or not,
-      // if not select instances
-      // else select containers (and follow subscriber chain to find the correct instance)
-
       let p;
 
+      // subscriber specific
       if(this.currentSubscriber){
-        let instances = [JSON.parse(service.tenant.service_specific_attribute).instance_id];
-        p = Ceilometer.getInstancesStats(instances);
+
+        let attr;
+        try {
+          attr = JSON.parse(service.tenant.service_specific_attribute);
+        }
+        catch(e){
+          attr = null;
+        }
+        
+        // if no instances are associated to the container
+        if(!attr || !attr.instance_id){
+          let d = $q.defer();
+          d.resolve([]);
+          p = d.promise;
+        }
+        else{
+          let instances = [attr.instance_id];
+          p = Ceilometer.getInstancesStats(instances)
+          .then((instances) => {
+            instances.map(i => {
+              i.container = {
+                name: `vcpe-${this.currentSubscriber.tags.sTag}-${this.currentSubscriber.tags.cTag}`
+              };
+              return i;
+            });
+
+            // TODO fetch container stats
+
+            return instances;
+          });
+        }
       }
+      // global scope
       else {
-        let param = {
+        const param = {
           'service_vsg': {kind: 'vCPE'},
           'service_vbng': {kind: 'vBNG'},
           'service_volt': {kind: 'vOLT'}
diff --git a/views/ngXosViews/diagnostic/src/js/logicTopology.js b/views/ngXosViews/diagnostic/src/js/logicTopology.js
index 8e7e741..f6798c6 100644
--- a/views/ngXosViews/diagnostic/src/js/logicTopology.js
+++ b/views/ngXosViews/diagnostic/src/js/logicTopology.js
@@ -50,17 +50,17 @@
         $rootScope.$on('instance.detail', (evt, service) => {
           ChartData.getInstanceStatus(service)
           .then((instances) => {
-            this.hideInstanceStats = false;
-            // HACK if array is empty wait for animation
-            if(instances.length === 0){
-              this.hideInstanceStats = true;
-              $timeout(() => {
-                this.selectedInstances = instances;
-              }, 500);
-            }
-            else{
-              this.selectedInstances = instances;
-            }
+            // this.hideInstanceStats = false;
+            // // HACK if array is empty wait for animation
+            // if(instances.length === 0){
+            //   this.hideInstanceStats = true;
+            //   $timeout(() => {
+            //     this.selectedInstances = instances;
+            //   }, 500);
+            // }
+            // else{
+            //   this.selectedInstances = instances;
+            // }
             LogicTopologyHelper.updateTree(svg);
           })
         })
diff --git a/views/ngXosViews/diagnostic/src/js/nodeDrawer.js b/views/ngXosViews/diagnostic/src/js/nodeDrawer.js
index 3007fd2..0249b3d 100644
--- a/views/ngXosViews/diagnostic/src/js/nodeDrawer.js
+++ b/views/ngXosViews/diagnostic/src/js/nodeDrawer.js
@@ -9,7 +9,7 @@
   var instanceId = 0;
 
   angular.module('xos.serviceTopology')
-  .service('NodeDrawer', function(d3, serviceTopologyConfig, RackHelper){
+  .service('NodeDrawer', function(d3, serviceTopologyConfig, RackHelper, lodash){
 
     var _this = this;
 
@@ -64,6 +64,9 @@
       nodes.each(d => {
         let [w, h] = RackHelper.getRackSize(d.computeNodes);
 
+        // TODO update instead of delete and redraw
+        nodes.select('g').remove();
+
         let rack = nodes
         .append('g');
 
@@ -74,7 +77,7 @@
         .transition()
         .duration(serviceTopologyConfig.duration)
         .attr({
-          transform: d => `translate(${- (w / 2)}, ${- (h / 2)})`
+          transform: () => `translate(${- (w / 2)}, ${- (h / 2)})`
         });
 
         rack
@@ -177,11 +180,120 @@
       return name
         .replace('app_', '')
         .replace('service_', '')
-        .replace('ovs_', '')
+        // .replace('ovs_', '')
         .replace('mysite_', '')
         .replace('_instance', '');
     };
 
+    const getInstanceStatusColor = (instance) => {
+      function startWith(val, string){
+        return string.substring(0, val.length) === val;
+      }
+
+      if(startWith('0 - ', instance.backend_status)){
+        return 'provisioning';
+      }
+      if(startWith('1 - ', instance.backend_status)){
+        return 'good';
+      }
+      if(startWith('2 - ', instance.backend_status)){
+        return 'bad';
+      }
+      else {
+        return '';
+      }
+    };
+
+    const showInstanceStats = (container, instance) => {
+
+      // NOTE this should be dinamically positioned
+      // base on the number of element present
+      const statsContainer = container.append('g')
+        .attr({
+          transform: `translate(200, -32)`,
+          class: 'stats-container'
+        });
+
+
+      statsContainer.append('line')
+        .attr({
+          x1: -120,
+          y1: 50,
+          x2: 0,
+          y2: 50,
+          stroke: 'black'
+        })
+
+      // NOTE rect should be dinamically sized base on the presence of a container
+      let statsHeight = 110;
+      let statsWidth = 200;
+
+      if (instance.container){
+        statsHeight += serviceTopologyConfig.container.height + (serviceTopologyConfig.container.margin * 2)
+      }
+
+      statsContainer.append('rect')
+        .attr({
+          width: statsWidth,
+          height: statsHeight
+        });
+
+      // add instance info
+      statsContainer.append('text')
+        .attr({
+          y: 15,
+          x: serviceTopologyConfig.instance.margin,
+          class: 'name'
+        })
+        .text(instance.humanReadableName)
+
+      statsContainer.append('text')
+        .attr({
+          y: 30,
+          x: serviceTopologyConfig.instance.margin,
+          class: 'ip'
+        })
+        .text(instance.ip)
+
+      // add stats
+      const interestingMeters = ['memory', 'memory.usage', 'cpu', 'vcpus'];
+
+      interestingMeters.forEach((m, i) => {
+        const meter = lodash.find(instance.stats, {meter: m});
+        statsContainer.append('text')
+        .attr({
+          y: 55 + (i * 15),
+          x: serviceTopologyConfig.instance.margin
+        })
+        .text(`${meter.description}: ${meter.value} ${meter.unit}`);
+      });
+
+      if(instance.container){
+        // draw container
+        
+        const containerBox = statsContainer.append('g')
+          .attr({
+            class: 'container',
+            transform: `translate(${serviceTopologyConfig.instance.margin}, 115)`
+          });
+
+        containerBox.append('rect')
+          .attr({
+            width: statsWidth - (serviceTopologyConfig.container.margin * 2),
+            height: serviceTopologyConfig.container.height,
+          });
+
+        containerBox.append('text')
+          .attr({
+            y: 20,
+            x: (statsWidth - (serviceTopologyConfig.container.margin * 2)) / 2,
+            'text-anchor': 'middle'
+          })
+          .text(instance.container.name)
+      }
+
+    };
+
     this.drawInstances = (container, instances) => {
       
       // TODO check for stats field in instance and draw popup
@@ -196,7 +308,7 @@
       instanceContainer
       .attr({
         transform: `translate(${width / 2}, ${ height / 2})`,
-        class: d => `instance ${d.selected ? 'active' : ''}`,
+        class: d => `instance ${d.selected ? 'active' : ''} ${getInstanceStatusColor(d)}`,
       })
       .transition()
       .duration(serviceTopologyConfig.duration)
@@ -223,16 +335,27 @@
         x: 40, //FIXME
         opacity: 0
       })
-      .text(d => formatInstanceName(d.name))
+      .text(d => formatInstanceName(d.humanReadableName))
       .transition()
       .duration(serviceTopologyConfig.duration)
       .attr({
         opacity: 1
       });
 
+      // if stats are attached and instance is active,
+      // draw stats
+      instanceContainer.each(function(instance){
+
+        const container = d3.select(this);
+
+        if(angular.isDefined(instance.stats) && instance.selected){
+          showInstanceStats(container, instance);
+        }
+      });
+
       instanceContainer
-      .on('click', d => {
-        console.log(d);
+      .on('click', function(d){
+        console.log(`Draw vignette with stats for instance: ${d.name}`);
       });
     };
 
diff --git a/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js b/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js
index 518c41a..d47bf24 100644
--- a/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js
+++ b/views/ngXosViews/diagnostic/src/js/serviceTopologyHelper.js
@@ -4,6 +4,7 @@
   angular.module('xos.serviceTopology')
   .service('ServiceTopologyHelper', function($rootScope, $window, $log, lodash, ServiceRelation, serviceTopologyConfig, d3){
 
+    // NOTE not used anymore
     const drawLegend = (svg) => {
       const legendContainer = svg.append('g')
         .attr({
@@ -122,7 +123,7 @@
           class: d => {
             return `node ${d.type}`
           },
-          transform: `translate(${source.y0}, ${source.x0})`
+          transform: d => (d.x && d.y) ? `translate(${d.y}, ${d.x})` : `translate(${source.y0}, ${source.x0})`
         });
 
       const subscriberNodes = nodeEnter.filter('.subscriber');