Fix bug 1276: collect metric from gnocchi first then ceilometer if it fails
[osm/MON.git] / osm_mon / collector / vnf_collectors / openstack.py
index bd2a617..7de93ec 100644 (file)
@@ -142,15 +142,15 @@ class OpenstackCollector(BaseVimCollector):
 
     def _get_backend(self, vim_account: dict):
         try:
-            ceilometer = CeilometerBackend(vim_account)
-            ceilometer.client.capabilities.get()
-            log.info("Using ceilometer backend to collect metric")
-            return ceilometer
-        except (HTTPException, EndpointNotFound):
             gnocchi = GnocchiBackend(vim_account)
             gnocchi.client.metric.list(limit=1)
             log.info("Using gnocchi backend to collect metric")
             return gnocchi
+        except (HTTPException, EndpointNotFound):
+            ceilometer = CeilometerBackend(vim_account)
+            ceilometer.client.capabilities.get()
+            log.info("Using ceilometer backend to collect metric")
+            return ceilometer
 
     def _get_metric_type(self, metric_name: str, interface_name: str) -> MetricType:
         if metric_name not in INTERFACE_METRICS:
@@ -232,17 +232,36 @@ class GnocchiBackend(OpenstackBackend):
         try:
             aggregation = METRIC_AGGREGATORS.get(openstack_metric_name)
 
-            measures = self.client.metric.get_measures(openstack_metric_name,
-                                                       aggregation=aggregation,
-                                                       start=time.time() - 1200,
-                                                       resource_id=resource_id)
-            # measures[-1][0] is the time of the reporting interval
-            # measures[-1][1] is the durcation of the reporting interval
-            # measures[-1][2] is the value of the metric
-            if measures:
-                value = measures[-1][2]
+            try:
+                measures = self.client.metric.get_measures(openstack_metric_name,
+                                                           aggregation=aggregation,
+                                                           start=time.time() - 1200,
+                                                           resource_id=resource_id)
+                if measures:
+                    value = measures[-1][2]
+            except gnocchiclient.exceptions.NotFound as e:
+                # CPU metric in previous Openstack versions do not support rate:mean aggregation method
+                if openstack_metric_name == "cpu":
+                    log.debug("No metric %s found for instance %s: %s", openstack_metric_name, resource_id, e)
+                    log.debug("Retrying to get metric %s for instance %s without aggregation",
+                              openstack_metric_name, resource_id)
+                    measures = self.client.metric.get_measures(openstack_metric_name,
+                                                               resource_id=resource_id,
+                                                               limit=1)
+                else:
+                    raise e
+                # measures[-1] is the last measure
+                # measures[-2] is the previous measure
+                # measures[x][2] is the value of the metric
+                if measures and len(measures) >= 2:
+                    value = measures[-1][2] - measures[-2][2]
+            if value:
+                # measures[-1][0] is the time of the reporting interval
+                # measures[-1][1] is the duration of the reporting interval
                 if aggregation:
                     # If this is an aggregate, we need to divide the total over the reported time period.
+                    # Even if the aggregation method is not supported by Openstack, the code will execute it
+                    # because aggregation is specified in METRIC_AGGREGATORS
                     value = value / measures[-1][1]
                 if openstack_metric_name in METRIC_MULTIPLIERS:
                     value = value * METRIC_MULTIPLIERS[openstack_metric_name]