Gerrit id-7270 Enhancing NBI to define APIs for metric collection 39/7439/4
authorvijay.r <vijay.r@tataelxsi.co.in>
Tue, 30 Apr 2019 12:25:49 +0000 (17:55 +0530)
committerrsvij <vijay.r@tataelxsi.co.in>
Wed, 15 May 2019 01:07:17 +0000 (02:07 +0100)
changes are made aligning to project architecture

Change-Id: Icde144c97ac29ff988c553c22406e357b099101c
Signed-off-by: vijay.r <vijay.r@tataelxsi.co.in>
Dockerfile.local
osm_nbi/engine.py
osm_nbi/nbi.cfg
osm_nbi/nbi.py
osm_nbi/pmjobs_topics.py [new file with mode: 0644]

index def89c4..7ac6091 100644 (file)
@@ -21,7 +21,7 @@ WORKDIR /app/NBI/osm_nbi
 RUN apt-get update && apt-get install -y git python3 python3-jsonschema \
     python3-pymongo python3-yaml python3-pip python3-keystoneclient \
     && pip3 install pip==9.0.3 \
-    && pip3 install aiokafka cherrypy==18.0.0 keystoneauth1 requests \
+    && pip3 install aiokafka aiohttp cherrypy==18.0.0 keystoneauth1 requests \
     && mkdir -p /app/storage/kafka && mkdir -p /app/log 
 
 # OSM_COMMON
@@ -90,6 +90,9 @@ ENV OSMNBI_AUTHENTICATION_BACKEND               internal
 # RBAC
 ENV OSMNBI_RBAC_RESOURCES_TO_OPERATIONS         /app/NBI/osm_nbi/resources_to_operations.yml
 ENV OSMNBI_RBAC_ROLES_TO_OPERATIONS             /app/NBI/osm_nbi/roles_to_operations.yml
+# prometheus
+ENV OSMNBI_PROMETHEUS_HOST                      prometheus
+ENV OSMNBI_PROMETHEUS_PORT                      9090
 
 # Copy the current directory contents into the container at /app
 ADD . /app/NBI
index db45ce7..5e42858 100644 (file)
@@ -27,6 +27,7 @@ from admin_topics import UserTopic, ProjectTopic, VimAccountTopic, WimAccountTop
 from admin_topics import UserTopicAuth, ProjectTopicAuth, RoleTopicAuth
 from descriptor_topics import VnfdTopic, NsdTopic, PduTopic, NstTopic
 from instance_topics import NsrTopic, VnfrTopic, NsLcmOpTopic, NsiTopic, NsiLcmOpTopic
+from pmjobs_topics import PmJobsTopic
 from base64 import b64encode
 from os import urandom, path
 from threading import Lock
@@ -52,6 +53,7 @@ class Engine(object):
         "nsis": NsiTopic,
         "nsilcmops": NsiLcmOpTopic
         # [NEW_TOPIC]: add an entry here
+        # "pm_jobs": PmJobsTopic will be added manually because it needs other parameters
     }
 
     def __init__(self):
@@ -147,6 +149,8 @@ class Engine(object):
                                                         self.operations)
                 else:
                     self.map_topic[topic] = topic_class(self.db, self.fs, self.msg)
+                self.map_topic[topic] = topic_class(self.db, self.fs, self.msg)
+            self.map_topic["pm_jobs"] = PmJobsTopic(config["prometheus"].get("host"), config["prometheus"].get("port"))
         except (DbException, FsException, MsgException) as e:
             raise EngineException(str(e), http_code=e.http_code)
 
index 81237cd..9f0eaa4 100644 (file)
@@ -65,6 +65,10 @@ name: "osm"
 # password: "password"
 # commonkey: "commonkey"
 
+[prometheus]
+host: "prometheus"         #hostname or IP
+port: 9090
+
 loglevel:  "DEBUG"
 #logfile: /var/log/osm/nbi-database.log
 
index fcc1e04..705979b 100644 (file)
@@ -337,6 +337,17 @@ class Server(object):
                                         },
                 }
             },
+            "nspm": {
+                "v1": {
+                    "pm_jobs": {
+                        "<ID>": {
+                            "reports": {
+                                "<ID>": {"METHODS": ("GET")}
+                            }
+                        },
+                    },
+                },
+            },
         }
 
     def _format_in(self, kwargs):
@@ -699,7 +710,7 @@ class Server(object):
             if not main_topic or not version or not topic:
                 raise NbiException("URL must contain at least 'main_topic/version/topic'",
                                    HTTPStatus.METHOD_NOT_ALLOWED)
-            if main_topic not in ("admin", "vnfpkgm", "nsd", "nslcm", "pdu", "nst", "nsilcm"):
+            if main_topic not in ("admin", "vnfpkgm", "nsd", "nslcm", "pdu", "nst", "nsilcm", "nspm"):
                 raise NbiException("URL main_topic '{}' not supported".format(main_topic),
                                    HTTPStatus.METHOD_NOT_ALLOWED)
             if version != 'v1':
@@ -723,7 +734,7 @@ class Server(object):
             engine_topic = topic
             if topic == "subscriptions":
                 engine_topic = main_topic + "_" + topic
-            if item:
+            if item and topic != "pm_jobs":
                 engine_topic = item
 
             if main_topic == "nsd":
@@ -763,6 +774,9 @@ class Server(object):
                 elif not _id:
                     outdata = self.engine.get_item_list(session, engine_topic, kwargs)
                 else:
+                    if item == "reports":
+                        # TODO check that project_id (_id in this context) has permissions
+                        _id = args[0]
                     outdata = self.engine.get_item(session, engine_topic, _id)
             elif method == "POST":
                 if topic in ("ns_descriptors_content", "vnf_packages_content", "netslice_templates_content"):
diff --git a/osm_nbi/pmjobs_topics.py b/osm_nbi/pmjobs_topics.py
new file mode 100644 (file)
index 0000000..5123cdc
--- /dev/null
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+
+# 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.
+
+
+import asyncio
+import aiohttp
+from base_topic import EngineException
+
+__author__ = "Vijay R S <vijay.r@tataelxsi.co.in>"
+
+
+class PmJobsTopic():
+    def __init__(self, host=None, port=None):
+        self.url = 'http://{}:{}'.format(host, port)
+        self.metric_list = ['cpu_utilization', 'average_memory_utilization', 'disk_read_ops',
+                            'disk_write_ops', 'disk_read_bytes', 'disk_write_bytes', 'packets_dropped',
+                            'packets_sent', 'packets_received']
+
+    async def _prom_metric_request(self, ns_id):
+        try:
+            async with aiohttp.ClientSession() as session:
+                data = []
+                for metlist in self.metric_list:
+                    request_url = self.url+'/api/v1/query?query=osm_'+metlist+"{ns_id='"+ns_id+"'}"
+                    async with session.get(request_url) as resp:
+                        resp = await resp.json()
+                        resp = resp['data']['result']
+                        if resp:
+                            data.append(resp)
+                return data
+        except aiohttp.client_exceptions.ClientConnectorError as e:
+            raise EngineException("Connection Failure: {}".format(e))
+
+    def show(self, session, ns_id):
+        loop = asyncio.new_event_loop()
+        asyncio.set_event_loop(loop)
+        prom_metric = loop.run_until_complete(self._prom_metric_request(ns_id))
+        metric = {}
+        metric_temp = []
+        for index_list in prom_metric:
+            for index in index_list:
+                process_metric = {'performanceValue': {'performanceValue': {}}}
+                process_metric['objectInstanceId'] = index['metric']['ns_id']
+                process_metric['performanceMetric'] = index['metric']['__name__']
+                process_metric['performanceValue']['timestamp'] = index['value'][0]
+                process_metric['performanceValue']['performanceValue']['performanceValue'] = index['value'][1]
+                process_metric['performanceValue']['performanceValue']['vnfMemberIndex'] \
+                    = index['metric']['vnf_member_index']
+                process_metric['performanceValue']['performanceValue']['vduName'] = index['metric']['vdu_name']
+                metric_temp.append(process_metric)
+        metric['entries'] = metric_temp
+        return metric