Generic ceilometer notification listener module

Change-Id: I00be2bf7eb07d1352b4cc2e28e384736e1b363b4
diff --git a/xos/api/tenant/monitoring/dashboard/ceilometerdashboard.py b/xos/api/tenant/monitoring/dashboard/ceilometerdashboard.py
index 1333d5a..1ab8d75 100644
--- a/xos/api/tenant/monitoring/dashboard/ceilometerdashboard.py
+++ b/xos/api/tenant/monitoring/dashboard/ceilometerdashboard.py
@@ -253,6 +253,35 @@
         # Here will be the cached Meter objects, that will be reused for
         # repeated listing.
         self._cached_meters = {}
+        self._cached_all_meters = []
+
+    def get_all(self):
+        if not self._cached_all_meters:
+            for meter in self._ceilometer_meter_list:
+                meter_info = self._all_meters_info.get(meter['name'], None)
+                if meter_info:
+                    label = meter_info["label"]
+                    description = meter_info["description"]
+                    meter_category = meter_info["type"]
+                else:
+                    label = ""
+                    description = ""
+                    meter_category = "Other"
+                meter["label"] = label
+                meter["description"] = description
+                meter["category"] = meter_category
+                if meter["project_id"] in self.tenant_map.keys():
+                    meter["slice"] = self.tenant_map[meter["project_id"]]["slice"]
+                    meter["service"] = self.tenant_map[meter["project_id"]]["service"]
+                else:
+                    meter["slice"] = meter["project_id"]
+                    meter["service"] = "Other"
+                if meter["resource_id"] in self.resource_map.keys():
+                    meter["resource_name"] = self.resource_map[meter["resource_id"]]
+
+                self._cached_all_meters.append(meter)
+
+        return self._cached_all_meters
 
     def list_all(self, only_meters=None, except_meters=None):
         """Returns a list of meters based on the meters names.
@@ -1253,18 +1282,7 @@
         tenant_map = getTenantControllerTenantMap(request.user)
         resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url, query=query)
         meters = Meters(request, ceilometer_url=tenant_ceilometer_url, query=query, tenant_map=tenant_map, resource_map=resource_map)
-        services = {
-            _('Nova'): meters.list_nova(),
-            _('Neutron'): meters.list_neutron(),
-            _('VSG'): meters.list_vcpe(),
-            _('VOLT'): meters.list_volt(),
-            _('SDN'): meters.list_sdn(),
-            _('BROADVIEW'): meters.list_broadview(),
-        }
-        meters = []
-        for service,smeters in services.iteritems():
-             meters.extend(smeters)
-        return Response(meters)
+        return Response(meters.get_all())
 
 class MeterStatisticsList(APIView):
     method_kind = "list"
@@ -1325,43 +1343,34 @@
         #Statistics query for all meter
         resource_map = get_resource_map(request, ceilometer_url=tenant_ceilometer_url, query=query)
         meters = Meters(request, ceilometer_url=tenant_ceilometer_url, query=query, tenant_map=tenant_map, resource_map=resource_map)
-        services = {
-            _('Nova'): meters.list_nova(),
-            _('Neutron'): meters.list_neutron(),
-            _('VSG'): meters.list_vcpe(),
-            _('VOLT'): meters.list_volt(),
-            _('SDN'): meters.list_sdn(),
-            _('BROADVIEW'): meters.list_broadview(),
-        }
         report_rows = []
-        for service,meters in services.items():
-            for meter in meters:
-                query = make_query(tenant_id=meter["project_id"],resource_id=meter["resource_id"])
-                if additional_query:
-                    query = query + additional_query
-                try:
-                    statistics = statistic_list(request, meter["name"],
-                                        ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
-                except Exception as e:
-                    logger.error('Exception during statistics query for meter %(meter)s and reason:%(reason)s' % {'meter':meter["name"], 'reason':str(e)})
-                    statistics = None
+        for meter in meters.get_all():
+            query = make_query(tenant_id=meter["project_id"],resource_id=meter["resource_id"])
+            if additional_query:
+                query = query + additional_query
+            try:
+                statistics = statistic_list(request, meter["name"],
+                                    ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
+            except Exception as e:
+                logger.error('Exception during statistics query for meter %(meter)s and reason:%(reason)s' % {'meter':meter["name"], 'reason':str(e)})
+                statistics = None
 
-                if not statistics:
-                    continue
-                statistic = statistics[-1]
-                row = {"name": 'none',
-                       "slice": meter["slice"],
-                       "project_id": meter["project_id"],
-                       "service": meter["service"],
-                       "resource_id": meter["resource_id"],
-                       "resource_name": meter["resource_name"],
-                       "meter": meter["name"],
-                       "description": meter["description"],
-                       "category": service,
-                       "time": statistic["period_end"],
-                       "value": statistic["avg"],
-                       "unit": meter["unit"]}
-                report_rows.append(row)
+            if not statistics:
+                continue
+            statistic = statistics[-1]
+            row = {"name": 'none',
+                   "slice": meter["slice"],
+                   "project_id": meter["project_id"],
+                   "service": meter["service"],
+                   "resource_id": meter["resource_id"],
+                   "resource_name": meter["resource_name"],
+                   "meter": meter["name"],
+                   "description": meter["description"],
+                   "category": meter["category"],
+                   "time": statistic["period_end"],
+                   "value": statistic["avg"],
+                   "unit": meter["unit"]}
+            report_rows.append(row)
 
         return Response(report_rows)
 
diff --git a/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services/cord/__init__.py b/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services/cord/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services/cord/__init__.py
diff --git a/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services/cord/notifications.py b/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services/cord/notifications.py
new file mode 100644
index 0000000..a832b01
--- /dev/null
+++ b/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services/cord/notifications.py
@@ -0,0 +1,69 @@
+#
+# Copyright 2012 New Dream Network, LLC (DreamHost)
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+"""Handler for producing network counter messages from Neutron notification
+   events.
+
+"""
+
+import oslo_messaging
+from oslo_config import cfg
+
+from ceilometer.agent import plugin_base
+from oslo_log import log
+from ceilometer import sample
+
+OPTS = [
+    cfg.StrOpt('cord_control_exchange',
+               default='cord',
+               help="Exchange name for CORD related notifications."),
+]
+
+cfg.CONF.register_opts(OPTS)
+
+LOG = log.getLogger(__name__)
+
+
+class CORDNotificationBase(plugin_base.NotificationBase):
+
+    resource_name = None
+    event_types = ['cord*']
+
+    def get_targets(self,conf):
+        """Return a sequence of oslo.messaging.Target
+
+        This sequence is defining the exchange and topics to be connected for
+        this plugin.
+        """
+        LOG.info("get_targets for CORD Notification Listener")
+        return [oslo_messaging.Target(topic=topic,
+                                      exchange=conf.cord_control_exchange)
+                for topic in self.get_notification_topics(conf)]
+
+    def process_notification(self, message):
+        LOG.info('Received CORD notification')
+        if 'counter_type' not in message['payload']:
+            meter_type = sample.TYPE_GAUGE
+        else:
+            meter_type = sample.TYPE_GAUGE if 'gauge' in message['payload']['counter_type'].lower() else sample.TYPE_DELTA if 'delta' in message['payload']['counter_type'].lower() else sample.TYPE_GAUGE
+
+        yield sample.Sample.from_notification(
+            name=message['payload']['counter_name'],
+            type=meter_type,
+            unit=message['payload']['counter_unit'],
+            volume=message['payload']['counter_volume'],
+            user_id=message['payload']['user_id'],
+            project_id=message['payload']['tenant_id'],
+            resource_id=message['payload']['resource_id'],
+            message=message)
diff --git a/xos/test/monitoring_test_exampleservicemetrics.yaml b/xos/test/monitoring_test_exampleservicemetrics.yaml
new file mode 100644
index 0000000..ee7fed1
--- /dev/null
+++ b/xos/test/monitoring_test_exampleservicemetrics.yaml
@@ -0,0 +1,9 @@
+---
+- hosts: localhost
+
+  vars_files:
+    - vars/defaults.yml
+
+  roles:
+    - common
+    - test-exampleservicemonitoring
diff --git a/xos/test/roles/common/tasks/main.yml b/xos/test/roles/common/tasks/main.yml
index 32c9613..6a9bbe6 100644
--- a/xos/test/roles/common/tasks/main.yml
+++ b/xos/test/roles/common/tasks/main.yml
@@ -13,5 +13,5 @@
   retries: 5
   delay: 60
   with_items:
-    - http://localhost:8888/api/service/monitoring/
-    - http://localhost:8888/api/tenant/monitoring/monitoringchannel/
+    - http://localhost:9000/api/service/monitoring/
+    - http://localhost:9000/api/tenant/monitoring/monitoringchannel/
diff --git a/xos/test/roles/test-exampleservicemonitoring/tasks/main.yml b/xos/test/roles/test-exampleservicemonitoring/tasks/main.yml
new file mode 100644
index 0000000..0190d80
--- /dev/null
+++ b/xos/test/roles/test-exampleservicemonitoring/tasks/main.yml
@@ -0,0 +1,28 @@
+---
+- name: Validate Monitoring URL is completely UP and metrics contain vSG related metrics
+  uri:
+    url: "{{monitoringservice.results[1].json[0].ceilometer_url}}v2/meters"
+    status_code: 200
+    return_content: yes
+    body_format: json
+    HEADER_Content-Type: "application/json"
+  register: metrics
+  until: "(metrics.status == 200) and (metrics.content|from_json|length>0) and ('exampleservice' in metrics.content)"
+  retries: 5
+  delay: 10
+
+- name: assert exampleservice metrics exampleservice.apache.total.accesses are present
+  assert:
+    that: "'exampleservice.apache.total.accesses' in metrics.content"
+    msg: "Metrics does not contains exampleservice.apache.total.accesses related statistics"
+
+- name: assert exampleservice metrics exampleservice.apache.uptime are present
+  assert:
+    that: "'exampleservice.apache.uptime' in metrics.content"
+    msg: "Metrics does not contains exampleservice.apache.uptime related statistics"
+
+- name: assert exampleservice metrics exampleservice.apache.reqpersec are present
+  assert:
+    that: "'exampleservice.apache.reqpersec' in metrics.content"
+    msg: "Metrics does not contains exampleservice.apache.reqpersec related statistics"
+