X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_nbi%2Fnbi.py;h=fa414f053384983fa4b1c786697f9f1bd27c8846;hb=a04d59bd184959b9ea88baccea05274b8851d3f5;hp=d5a81ce46f8b8993bdec1daaf92bfda96f43c21d;hpb=5758955b7b394517ff5caf5506a4400cdc5aa372;p=osm%2FNBI.git diff --git a/osm_nbi/nbi.py b/osm_nbi/nbi.py index d5a81ce4..fa414f05 100644 --- a/osm_nbi/nbi.py +++ b/osm_nbi/nbi.py @@ -85,7 +85,9 @@ URL: /osm GET POST terminate O5 action O scale O5 - heal 5 + migrate O + update 05 + heal O5 /ns_lcm_op_occs 5 5 / 5 5 5 TO BE COMPLETED 5 5 @@ -170,7 +172,7 @@ query string: ADMIN: To act as an administrator or a different project PUBLIC: To get public descriptors or set a descriptor as public SET_PROJECT: To make a descriptor available for other project - + Header field name Reference Example Descriptions Accept IETF RFC 7231 [19] application/json Content-Types that are acceptable for the response. This header field shall be present if the response is expected to have a non-empty message body. @@ -431,6 +433,10 @@ valid_url_methods = { "": { "METHODS": ("GET", "DELETE"), "ROLE_PERMISSION": "ns_instances:id:", + "heal": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "ns_instances:id:heal:", + }, "scale": { "METHODS": ("POST",), "ROLE_PERMISSION": "ns_instances:id:scale:", @@ -443,10 +449,22 @@ valid_url_methods = { "METHODS": ("POST",), "ROLE_PERMISSION": "ns_instances:id:instantiate:", }, + "migrate": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "ns_instances:id:migrate:", + }, "action": { "METHODS": ("POST",), "ROLE_PERMISSION": "ns_instances:id:action:", }, + "update": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "ns_instances:id:update:", + }, + "verticalscale": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "ns_instances:id:verticalscale:", + }, }, }, "ns_lcm_op_occs": { @@ -477,6 +495,46 @@ valid_url_methods = { }, } }, + "vnflcm": { + "v1": { + "vnf_instances": { + "METHODS": ("GET", "POST"), + "ROLE_PERMISSION": "vnflcm_instances:", + "": { + "METHODS": ("GET", "DELETE"), + "ROLE_PERMISSION": "vnflcm_instances:id:", + "scale": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "vnflcm_instances:id:scale:", + }, + "terminate": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "vnflcm_instances:id:terminate:", + }, + "instantiate": { + "METHODS": ("POST",), + "ROLE_PERMISSION": "vnflcm_instances:id:instantiate:", + }, + }, + }, + "vnf_lcm_op_occs": { + "METHODS": ("GET",), + "ROLE_PERMISSION": "vnf_instances:opps:", + "": { + "METHODS": ("GET",), + "ROLE_PERMISSION": "vnf_instances:opps:id:", + }, + }, + "subscriptions": { + "METHODS": ("GET", "POST"), + "ROLE_PERMISSION": "vnflcm_subscriptions:", + "": { + "METHODS": ("GET", "DELETE"), + "ROLE_PERMISSION": "vnflcm_subscriptions:id:", + }, + }, + } + }, "nst": { "v1": { "netslice_templates_content": { @@ -569,6 +627,18 @@ valid_url_methods = { }, }, }, + "nsfm": { + "v1": { + "alarms": { + "METHODS": ("GET", "PATCH"), + "ROLE_PERMISSION": "alarms:", + "": { + "METHODS": ("GET", "PATCH"), + "ROLE_PERMISSION": "alarms:id:", + }, + } + }, + }, } @@ -589,6 +659,7 @@ class Server(object): self.engine = Engine(self.authenticator) def _format_in(self, kwargs): + error_text = "" # error_text must be initialized outside try try: indata = None if cherrypy.request.body.length: @@ -823,6 +894,142 @@ class Server(object): if token_info.get("id"): cherrypy.request.login += ";session=" + token_info["id"][0:12] + # NS Fault Management + @cherrypy.expose + def nsfm( + self, + version=None, + topic=None, + uuid=None, + project_name=None, + ns_id=None, + *args, + **kwargs + ): + if topic == "alarms": + try: + method = cherrypy.request.method + role_permission = self._check_valid_url_method( + method, "nsfm", version, topic, None, None, *args + ) + query_string_operations = self._extract_query_string_operations( + kwargs, method + ) + + self.authenticator.authorize( + role_permission, query_string_operations, None + ) + + # to handle get request + if cherrypy.request.method == "GET": + # if request is on basis of uuid + if uuid and uuid != "None": + try: + alarm = self.engine.db.get_one("alarms", {"uuid": uuid}) + alarm_action = self.engine.db.get_one( + "alarms_action", {"uuid": uuid} + ) + alarm.update(alarm_action) + vnf = self.engine.db.get_one( + "vnfrs", {"nsr-id-ref": alarm["tags"]["ns_id"]} + ) + alarm["vnf-id"] = vnf["_id"] + return self._format_out(str(alarm)) + except Exception: + return self._format_out("Please provide valid alarm uuid") + elif ns_id and ns_id != "None": + # if request is on basis of ns_id + try: + alarms = self.engine.db.get_list( + "alarms", {"tags.ns_id": ns_id} + ) + for alarm in alarms: + alarm_action = self.engine.db.get_one( + "alarms_action", {"uuid": alarm["uuid"]} + ) + alarm.update(alarm_action) + return self._format_out(str(alarms)) + except Exception: + return self._format_out("Please provide valid ns id") + else: + # to return only alarm which are related to given project + project = self.engine.db.get_one( + "projects", {"name": project_name} + ) + project_id = project.get("_id") + ns_list = self.engine.db.get_list( + "nsrs", {"_admin.projects_read": project_id} + ) + ns_ids = [] + for ns in ns_list: + ns_ids.append(ns.get("_id")) + alarms = self.engine.db.get_list("alarms") + alarm_list = [ + alarm + for alarm in alarms + if alarm["tags"]["ns_id"] in ns_ids + ] + for alrm in alarm_list: + action = self.engine.db.get_one( + "alarms_action", {"uuid": alrm.get("uuid")} + ) + alrm.update(action) + return self._format_out(str(alarm_list)) + # to handle patch request for alarm update + elif cherrypy.request.method == "PATCH": + data = yaml.load(cherrypy.request.body, Loader=yaml.SafeLoader) + try: + # check if uuid is valid + self.engine.db.get_one("alarms", {"uuid": data.get("uuid")}) + except Exception: + return self._format_out("Please provide valid alarm uuid.") + if data.get("is_enable") is not None: + if data.get("is_enable"): + alarm_status = "ok" + else: + alarm_status = "disabled" + self.engine.db.set_one( + "alarms", + {"uuid": data.get("uuid")}, + {"alarm_status": alarm_status}, + ) + else: + self.engine.db.set_one( + "alarms", + {"uuid": data.get("uuid")}, + {"threshold": data.get("threshold")}, + ) + return self._format_out("Alarm updated") + except Exception as e: + if isinstance( + e, + ( + NbiException, + EngineException, + DbException, + FsException, + MsgException, + AuthException, + ValidationError, + AuthconnException, + ), + ): + http_code_value = cherrypy.response.status = e.http_code.value + http_code_name = e.http_code.name + cherrypy.log("Exception {}".format(e)) + else: + http_code_value = ( + cherrypy.response.status + ) = HTTPStatus.BAD_REQUEST.value # INTERNAL_SERVER_ERROR + cherrypy.log("CRITICAL: Exception {}".format(e), traceback=True) + http_code_name = HTTPStatus.BAD_REQUEST.name + problem_details = { + "code": http_code_name, + "status": http_code_value, + "detail": str(e), + } + return self._format_out(problem_details) + @cherrypy.expose def token(self, method, token_id=None, kwargs=None): token_info = None @@ -854,11 +1061,17 @@ class Server(object): outdata = token_info = self.authenticator.new_token( token_info, indata, cherrypy.request.remote ) - cherrypy.session["Authorization"] = outdata["_id"] + cherrypy.session["Authorization"] = outdata["_id"] # pylint: disable=E1101 self._set_location_header("admin", "v1", "tokens", outdata["_id"]) # for logging self._format_login(token_info) - + # password expiry check + if self.authenticator.check_password_expiry(outdata): + outdata = { + "id": outdata["id"], + "message": "change_password", + "user_id": outdata["user_id"], + } # cherrypy.response.cookie["Authorization"] = outdata["id"] # cherrypy.response.cookie["Authorization"]['expires'] = 3600 elif method == "DELETE": @@ -871,7 +1084,7 @@ class Server(object): token_id = token_info["_id"] outdata = self.authenticator.del_token(token_id) token_info = None - cherrypy.session["Authorization"] = "logout" + cherrypy.session["Authorization"] = "logout" # pylint: disable=E1101 # cherrypy.response.cookie["Authorization"] = token_id # cherrypy.response.cookie["Authorization"]['expires'] = 0 else: @@ -899,7 +1112,8 @@ class Server(object): elif args and args[0] == "init": try: # self.engine.load_dbase(cherrypy.request.app.config) - self.engine.create_admin() + pid = self.authenticator.create_admin_project() + self.authenticator.create_admin_user(pid) return "Done. User 'admin', password 'admin' created" except Exception: cherrypy.response.status = HTTPStatus.FORBIDDEN.value @@ -977,10 +1191,12 @@ class Server(object): + " headers: {}\n".format(cherrypy.request.headers) + " path_info: {}\n".format(cherrypy.request.path_info) + " query_string: {}\n".format(cherrypy.request.query_string) - + " session: {}\n".format(cherrypy.session) + + " session: {}\n".format(cherrypy.session) # pylint: disable=E1101 + " cookie: {}\n".format(cherrypy.request.cookie) + " method: {}\n".format(cherrypy.request.method) - + " session: {}\n".format(cherrypy.session.get("fieldname")) + + " session: {}\n".format( + cherrypy.session.get("fieldname") # pylint: disable=E1101 + ) + " body:\n" ) return_text += " length: {}\n".format(cherrypy.request.body.length) @@ -1193,6 +1409,7 @@ class Server(object): "nst", "nsilcm", "nspm", + "vnflcm", ): raise NbiException( "URL main_topic '{}' not supported".format(main_topic), @@ -1247,6 +1464,9 @@ class Server(object): engine_topic = "nslcmops" if topic == "vnfrs" or topic == "vnf_instances": engine_topic = "vnfrs" + elif main_topic == "vnflcm": + if topic == "vnf_lcm_op_occs": + engine_topic = "vnflcmops" elif main_topic == "nst": engine_topic = "nsts" elif main_topic == "nsilcm": @@ -1300,7 +1520,9 @@ class Server(object): filter_q = None if "vcaStatusRefresh" in kwargs: filter_q = {"vcaStatusRefresh": kwargs["vcaStatusRefresh"]} - outdata = self.engine.get_item(engine_session, engine_topic, _id, filter_q, True) + outdata = self.engine.get_item( + engine_session, engine_topic, _id, filter_q, True + ) elif method == "POST": cherrypy.response.status = HTTPStatus.CREATED.value @@ -1404,6 +1626,17 @@ class Server(object): "_links": link, } cherrypy.response.status = HTTPStatus.CREATED.value + elif topic == "vnf_instances" and item: + indata["lcmOperationType"] = item + indata["vnfInstanceId"] = _id + _id, _ = self.engine.new_item( + rollback, engine_session, "vnflcmops", indata, kwargs + ) + self._set_location_header( + main_topic, version, "vnf_lcm_op_occs", _id + ) + outdata = {"id": _id} + cherrypy.response.status = HTTPStatus.ACCEPTED.value else: _id, op_id = self.engine.new_item( rollback, @@ -1556,7 +1789,6 @@ class Server(object): self.engine.db.del_list( rollback_item["topic"], rollback_item["filter"], - fail_on_empty=False, ) else: self.engine.db.del_one( @@ -1632,7 +1864,9 @@ def _start_service(): except ValueError as e: cherrypy.log.error("Ignoring environ '{}': " + str(e)) except Exception as e: - cherrypy.log.warn("skipping environ '{}' on exception '{}'".format(k, e)) + cherrypy.log( + "WARNING: skipping environ '{}' on exception '{}'".format(k, e) + ) if update_dict: cherrypy.config.update(update_dict)