Added Instance stats to d3 and drawing container
diff --git a/views/ngXosViews/diagnostic/mocks/data/instances.json b/views/ngXosViews/diagnostic/mocks/data/instances.json
index a60b696..ec0f598 100644
--- a/views/ngXosViews/diagnostic/mocks/data/instances.json
+++ b/views/ngXosViews/diagnostic/mocks/data/instances.json
@@ -261,7 +261,7 @@
         "enacted": "2016-02-17T22:05:44.887Z", 
         "policed": "2016-02-17T22:05:45.538Z", 
         "backend_register": "{\"next_run\": 0, \"last_success\": 1455746744.887768, \"exponent\": 0}", 
-        "backend_status": "1 - OK", 
+        "backend_status": "0 - Provisioning in progress", 
         "deleted": false, 
         "write_protect": false, 
         "lazy_blocked": false, 
@@ -285,5 +285,38 @@
             7, 
             2
         ]
+    },
+    {
+        "humanReadableName": "mysite_vsg-3", 
+        "id": 12, 
+        "created": "2016-02-17T22:00:58.015Z", 
+        "updated": "2016-02-17T22:05:44.877Z", 
+        "enacted": "2016-02-17T22:05:44.887Z", 
+        "policed": "2016-02-17T22:05:45.538Z", 
+        "backend_register": "{\"next_run\": 0, \"last_success\": 1455746744.887768, \"exponent\": 0}", 
+        "backend_status": "2 - Error", 
+        "deleted": false, 
+        "write_protect": false, 
+        "lazy_blocked": false, 
+        "no_sync": false, 
+        "instance_id": "instance-00000004", 
+        "instance_uuid": "075a3ae4-9e76-4198-8e6b-67c67b996746", 
+        "name": "mysite_vsg", 
+        "instance_name": "mysite_vsg-3", 
+        "ip": "130.127.133.90", 
+        "image": 1, 
+        "creator": 1, 
+        "slice": 1, 
+        "deployment": 1, 
+        "node": 3, 
+        "numberCores": 0, 
+        "flavor": 1, 
+        "userData": null, 
+        "networks": [
+            1, 
+            6, 
+            7, 
+            2
+        ]
     }
 ]
\ No newline at end of file
diff --git a/views/ngXosViews/diagnostic/mocks/data/tenants.json b/views/ngXosViews/diagnostic/mocks/data/tenants.json
index 77bea93..5d6fb15 100644
--- a/views/ngXosViews/diagnostic/mocks/data/tenants.json
+++ b/views/ngXosViews/diagnostic/mocks/data/tenants.json
@@ -206,5 +206,28 @@
         "service_specific_id": null, 
         "service_specific_attribute": "{\"instance_id\": 11, \"creator_id\": 1}", 
         "connect_method": "na"
+    },
+    {
+        "humanReadableName": "vCPE-tenant-5", 
+        "id": 14, 
+        "created": "2016-02-17T19:36:04.650Z", 
+        "updated": "2016-02-17T20:55:18.115Z", 
+        "enacted": null, 
+        "policed": null, 
+        "backend_register": "{\"next_run\": 1455771318.072057, \"last_failure\": 1455742518.072061, \"last_success\": 1455737797.006782, \"exponent\": 871, \"failures\": 871}", 
+        "backend_status": "2 - Exception('defer object vCPE-tenant-4 due to waiting on instance.instance_name',)", 
+        "deleted": false, 
+        "write_protect": false, 
+        "lazy_blocked": false, 
+        "no_sync": false, 
+        "kind": "vCPE", 
+        "provider_service": 2, 
+        "subscriber_service": null, 
+        "subscriber_tenant": 3, 
+        "subscriber_user": null, 
+        "subscriber_root": null, 
+        "service_specific_id": null, 
+        "service_specific_attribute": "{\"instance_id\": 12, \"creator_id\": 1}", 
+        "connect_method": "na"
     }
 ]
\ No newline at end of file
diff --git a/views/ngXosViews/diagnostic/src/css/serviceTopology.css b/views/ngXosViews/diagnostic/src/css/serviceTopology.css
index 4b88ccb..9d9aa60 100644
--- a/views/ngXosViews/diagnostic/src/css/serviceTopology.css
+++ b/views/ngXosViews/diagnostic/src/css/serviceTopology.css
@@ -105,6 +105,40 @@
     stroke-width: 1px;   
 }
 
+logic-topology .node .instance.active.good > rect{
+    fill: green;
+}
+
+logic-topology .node .instance.active.provisioning > rect{
+    fill: yellow;
+}
+
+logic-topology .node .instance.active.bad > rect{
+    fill: red;
+}
+
+/* INSTANCE STATS */
+
+logic-topology .node .instance .stats-container rect {
+  fill: white;
+}
+
+logic-topology .node .instance .stats-container text.name{
+  font-weight: bold;
+}
+
+logic-topology .node .instance .stats-container text.ip{
+  font-style: italic;
+  font-size: 10px;
+}
+
+/* CONTAINERS */
+logic-topology .node .container rect{
+  fill: #eee;
+  stroke: steelblue;
+  stroke-width: 1px;
+}
+
 /* LEGEND */
 
 .legend {
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');
diff --git a/views/ngXosViews/diagnostic/src/templates/subscriber-modal.tpl.html b/views/ngXosViews/diagnostic/src/templates/subscriber-modal.tpl.html
index 9c005a3..7672a29 100644
--- a/views/ngXosViews/diagnostic/src/templates/subscriber-modal.tpl.html
+++ b/views/ngXosViews/diagnostic/src/templates/subscriber-modal.tpl.html
@@ -1,5 +1,5 @@
 <div class="modal fade" ng-class="{in: vm.open}" tabindex="-1" role="dialog">
-  <div class="modal-dialog">
+  <div class="modal-dialog modal-sm">
     <div class="modal-content">
       <div class="modal-header">
         <button ng-click="vm.close()"  type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>