Gerrit id-7270 Enhancing NBI to define APIs for metric collection
[osm/NBI.git] / osm_nbi / nbi.py
index a1e8b50..705979b 100644 (file)
@@ -27,6 +27,7 @@ import sys
 from authconn import AuthException
 from auth import Authenticator
 from engine import Engine, EngineException
 from authconn import AuthException
 from auth import Authenticator
 from engine import Engine, EngineException
+from subscriptions import SubscriptionThread
 from validation import ValidationError
 from osm_common.dbbase import DbException
 from osm_common.fsbase import FsException
 from validation import ValidationError
 from osm_common.dbbase import DbException
 from osm_common.fsbase import FsException
@@ -41,6 +42,9 @@ __version__ = "0.1.3"
 version_date = "Jan 2019"
 database_version = '1.0'
 auth_database_version = '1.0'
 version_date = "Jan 2019"
 database_version = '1.0'
 auth_database_version = '1.0'
+nbi_server = None           # instance of Server class
+subscription_thread = None  # instance of SubscriptionThread class
+
 
 """
 North Bound Interface  (O: OSM specific; 5,X: SOL005 not implemented yet; O5: SOL005 implemented)
 
 """
 North Bound Interface  (O: OSM specific; 5,X: SOL005 not implemented yet; O5: SOL005 implemented)
@@ -90,7 +94,7 @@ URL: /osm                                                       GET     POST
                 /<subscriptionId>                               5                       X
 
         /pdu/v1
                 /<subscriptionId>                               5                       X
 
         /pdu/v1
-            /pdu_descriptor                                     O       O
+            /pdu_descriptors                                    O       O
                 /<id>                                           O               O       O       O
 
         /admin/v1
                 /<id>                                           O               O       O       O
 
         /admin/v1
@@ -207,8 +211,12 @@ class Server(object):
                               "<ID>": {"METHODS": ("GET", "POST", "DELETE", "PATCH", "PUT")}
                               },
                     "projects": {"METHODS": ("GET", "POST"),
                               "<ID>": {"METHODS": ("GET", "POST", "DELETE", "PATCH", "PUT")}
                               },
                     "projects": {"METHODS": ("GET", "POST"),
-                                 "<ID>": {"METHODS": ("GET", "DELETE")}
+                                 # Added PUT to allow Project Name modification
+                                 "<ID>": {"METHODS": ("GET", "DELETE", "PUT")}
                                  },
                                  },
+                    "roles": {"METHODS": ("GET", "POST"),
+                              "<ID>": {"METHODS": ("GET", "POST", "DELETE")}
+                              },
                     "vims": {"METHODS": ("GET", "POST"),
                              "<ID>": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")}
                              },
                     "vims": {"METHODS": ("GET", "POST"),
                              "<ID>": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")}
                              },
@@ -329,6 +337,17 @@ class Server(object):
                                         },
                 }
             },
                                         },
                 }
             },
+            "nspm": {
+                "v1": {
+                    "pm_jobs": {
+                        "<ID>": {
+                            "reports": {
+                                "<ID>": {"METHODS": ("GET")}
+                            }
+                        },
+                    },
+                },
+            },
         }
 
     def _format_in(self, kwargs):
         }
 
     def _format_in(self, kwargs):
@@ -691,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 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':
                 raise NbiException("URL main_topic '{}' not supported".format(main_topic),
                                    HTTPStatus.METHOD_NOT_ALLOWED)
             if version != 'v1':
@@ -715,7 +734,7 @@ class Server(object):
             engine_topic = topic
             if topic == "subscriptions":
                 engine_topic = main_topic + "_" + topic
             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":
                 engine_topic = item
 
             if main_topic == "nsd":
@@ -733,7 +752,7 @@ class Server(object):
             elif main_topic == "nsilcm":
                 engine_topic = "nsis"
                 if topic == "nsi_lcm_op_occs":
             elif main_topic == "nsilcm":
                 engine_topic = "nsis"
                 if topic == "nsi_lcm_op_occs":
-                    engine_topic = "nsilcmops" 
+                    engine_topic = "nsilcmops"
             elif main_topic == "pdu":
                 engine_topic = "pdus"
             if engine_topic == "vims":   # TODO this is for backward compatibility, it will remove in the future
             elif main_topic == "pdu":
                 engine_topic = "pdus"
             if engine_topic == "vims":   # TODO this is for backward compatibility, it will remove in the future
@@ -755,6 +774,9 @@ class Server(object):
                 elif not _id:
                     outdata = self.engine.get_item_list(session, engine_topic, kwargs)
                 else:
                 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"):
                     outdata = self.engine.get_item(session, engine_topic, _id)
             elif method == "POST":
                 if topic in ("ns_descriptors_content", "vnf_packages_content", "netslice_templates_content"):
@@ -793,7 +815,7 @@ class Server(object):
                     indata["nsiInstanceId"] = _id
                     self.engine.new_item(rollback, session, "nsilcmops", indata, kwargs)
                     outdata = {"id": _id}
                     indata["nsiInstanceId"] = _id
                     self.engine.new_item(rollback, session, "nsilcmops", indata, kwargs)
                     outdata = {"id": _id}
-                    
+
                 elif topic == "netslice_instances" and item:
                     indata["lcmOperationType"] = item
                     indata["nsiInstanceId"] = _id
                 elif topic == "netslice_instances" and item:
                     indata["lcmOperationType"] = item
                     indata["nsiInstanceId"] = _id
@@ -904,6 +926,8 @@ def _start_service():
     Set database, storage, message configuration
     Init database with admin/admin user password
     """
     Set database, storage, message configuration
     Init database with admin/admin user password
     """
+    global nbi_server
+    global subscription_thread
     cherrypy.log.error("Starting osm_nbi")
     # update general cherrypy configuration
     update_dict = {}
     cherrypy.log.error("Starting osm_nbi")
     # update general cherrypy configuration
     update_dict = {}
@@ -988,6 +1012,11 @@ def _start_service():
     cherrypy.tree.apps['/osm'].root.engine.init_db(target_version=database_version)
     cherrypy.tree.apps['/osm'].root.authenticator.init_db(target_version=auth_database_version)
 
     cherrypy.tree.apps['/osm'].root.engine.init_db(target_version=database_version)
     cherrypy.tree.apps['/osm'].root.authenticator.init_db(target_version=auth_database_version)
 
+    # start subscriptions thread:
+    subscription_thread = SubscriptionThread(config=engine_config, engine=nbi_server.engine)
+    subscription_thread.start()
+    # Do not capture except SubscriptionException
+
     # load and print version. Ignore possible errors, e.g. file not found
     try:
         with open("{}/version".format(engine_config["/static"]['tools.staticdir.dir'])) as version_file:
     # load and print version. Ignore possible errors, e.g. file not found
     try:
         with open("{}/version".format(engine_config["/static"]['tools.staticdir.dir'])) as version_file:
@@ -1002,11 +1031,15 @@ def _stop_service():
     Callback function called when cherrypy.engine stops
     TODO: Ending database connections.
     """
     Callback function called when cherrypy.engine stops
     TODO: Ending database connections.
     """
+    global subscription_thread
+    subscription_thread.terminate()
+    subscription_thread = None
     cherrypy.tree.apps['/osm'].root.engine.stop()
     cherrypy.log.error("Stopping osm_nbi")
 
 
 def nbi(config_file):
     cherrypy.tree.apps['/osm'].root.engine.stop()
     cherrypy.log.error("Stopping osm_nbi")
 
 
 def nbi(config_file):
+    global nbi_server
     # conf = {
     #     '/': {
     #         #'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
     # conf = {
     #     '/': {
     #         #'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
@@ -1024,9 +1057,10 @@ def nbi(config_file):
     # cherrypy.config.update({'tools.auth_basic.on': True,
     #    'tools.auth_basic.realm': 'localhost',
     #    'tools.auth_basic.checkpassword': validate_password})
     # cherrypy.config.update({'tools.auth_basic.on': True,
     #    'tools.auth_basic.realm': 'localhost',
     #    'tools.auth_basic.checkpassword': validate_password})
+    nbi_server = Server()
     cherrypy.engine.subscribe('start', _start_service)
     cherrypy.engine.subscribe('stop', _stop_service)
     cherrypy.engine.subscribe('start', _start_service)
     cherrypy.engine.subscribe('stop', _stop_service)
-    cherrypy.quickstart(Server(), '/osm', config_file)
+    cherrypy.quickstart(nbi_server, '/osm', config_file)
 
 
 def usage():
 
 
 def usage():