Bug 1976: MON fails to collect disk metrics fixed
[osm/MON.git] / osm_mon / collector / vnf_collectors / openstack.py
index 525bd00..da17202 100644 (file)
@@ -55,6 +55,16 @@ METRIC_MAPPINGS = {
     "cpu_utilization": "cpu",
 }
 
+# Metrics which have new names in Rocky and higher releases
+METRIC_MAPPINGS_FOR_ROCKY_AND_NEWER_RELEASES = {
+    "disk_read_ops": "disk.device.read.requests",
+    "disk_write_ops": "disk.device.write.requests",
+    "disk_read_bytes": "disk.device.read.bytes",
+    "disk_write_bytes": "disk.device.write.bytes",
+    "packets_received": "network.incoming.packets",
+    "packets_sent": "network.outgoing.packets"
+}
+
 METRIC_MULTIPLIERS = {"cpu": 0.0000001}
 
 METRIC_AGGREGATORS = {"cpu": "rate:mean"}
@@ -66,11 +76,19 @@ INTERFACE_METRICS = [
     "packets_sent",
 ]
 
+INSTANCE_DISK = [
+    "disk_read_ops",
+    "disk_write_ops",
+    "disk_read_bytes",
+    "disk_write_bytes",
+]
+
 
 class MetricType(Enum):
     INSTANCE = "instance"
     INTERFACE_ALL = "interface_all"
     INTERFACE_ONE = "interface_one"
+    INSTANCEDISK = 'instancedisk'
 
 
 class OpenstackCollector(BaseVimCollector):
@@ -137,6 +155,20 @@ class OpenstackCollector(BaseVimCollector):
                         value = self.backend.collect_metric(
                             metric_type, openstack_metric_name, resource_id
                         )
+
+                        if value is None and metric_name in METRIC_MAPPINGS_FOR_ROCKY_AND_NEWER_RELEASES:
+                            # Reattempting metric collection with new metric names.
+                            # Some metric names have changed in newer Openstack releases
+                            log.info(
+                                "Reattempting metric collection for type: %s and name: %s and resource_id %s",
+                                metric_type,
+                                metric_name,
+                                resource_id
+                            )
+                            openstack_metric_name = METRIC_MAPPINGS_FOR_ROCKY_AND_NEWER_RELEASES[metric_name]
+                            value = self.backend.collect_metric(
+                                metric_type, openstack_metric_name, resource_id
+                            )
                         if value is not None:
                             log.info("value: %s", value)
                             metric = VnfMetric(
@@ -172,7 +204,10 @@ class OpenstackCollector(BaseVimCollector):
 
     def _get_metric_type(self, metric_name: str) -> MetricType:
         if metric_name not in INTERFACE_METRICS:
-            return MetricType.INSTANCE
+            if metric_name not in INSTANCE_DISK:
+                return MetricType.INSTANCE
+            else:
+                return MetricType.INSTANCEDISK
         else:
             return MetricType.INTERFACE_ALL
 
@@ -206,6 +241,9 @@ class GnocchiBackend(OpenstackBackend):
         elif metric_type == MetricType.INSTANCE:
             return self._collect_instance_metric(metric_name, resource_id)
 
+        elif metric_type == MetricType.INSTANCEDISK:
+            return self._collect_instance_disk_metric(metric_name, resource_id)
+
         else:
             raise Exception("Unknown metric type %s" % metric_type.value)
 
@@ -224,7 +262,6 @@ class GnocchiBackend(OpenstackBackend):
                     if not total_measure:
                         total_measure = 0.0
                     total_measure += measures[-1][2]
-
             except (gnocchiclient.exceptions.NotFound, TypeError) as e:
                 # Gnocchi in some Openstack versions raise TypeError instead of NotFound
                 log.debug(
@@ -235,6 +272,25 @@ class GnocchiBackend(OpenstackBackend):
                 )
         return total_measure
 
+    def _collect_instance_disk_metric(self, openstack_metric_name, resource_id):
+        value = None
+        instances = self.client.resource.search(
+            resource_type='instance_disk',
+            query={'=': {'instance_id': resource_id}},
+        )
+        for instance in instances:
+            try:
+                measures = self.client.metric.get_measures(
+                    openstack_metric_name, resource_id=instance['id'], limit=1
+                )
+                if measures:
+                    value = measures[-1][2]
+
+            except gnocchiclient.exceptions.NotFound as e:
+                log.debug("No metric %s found for instance disk %s: %s", openstack_metric_name,
+                          instance['id'], e)
+        return value
+
     def _collect_instance_metric(self, openstack_metric_name, resource_id):
         value = None
         try: