X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fnbi.py;h=2dfeb22e52bc5398ff740be4d92ea5238203cb1c;hp=aeff32c955389fd4a289ce22296ba58584477815;hb=f717cbe40358a8a8246d7936064cf235e2ff7f79;hpb=ba0dbed4d7fe4cd1ee800a4a3402157224fd7aff diff --git a/osm_nbi/nbi.py b/osm_nbi/nbi.py index aeff32c..2dfeb22 100644 --- a/osm_nbi/nbi.py +++ b/osm_nbi/nbi.py @@ -1,6 +1,19 @@ #!/usr/bin/python3 # -*- 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 cherrypy import time import json @@ -14,6 +27,7 @@ import sys from authconn import AuthException from auth import Authenticator from engine import Engine, EngineException +from validation import ValidationError from osm_common.dbbase import DbException from osm_common.fsbase import FsException from osm_common.msgbase import MsgException @@ -118,6 +132,10 @@ URL: /osm GET POST query string: Follows SOL005 section 4.3.2 It contains extra METHOD to override http method, FORCE to force. + simpleFilterExpr := ["."]*["."]"="[","]* + filterExpr := ["&"]* + op := "eq" | "neq" (or "ne") | "gt" | "lt" | "gte" | "lte" | "cont" | "ncont" + attrName := string For filtering inside array, it must select the element of the array, or add ANYINDEX to apply the filtering over any item of the array, that is, pass if any item of the array pass the filter. It allows both ne and neq for not equal @@ -214,7 +232,7 @@ class Server(object): "": {"METHODS": ("GET", "PUT", "DELETE")} }, "ns_descriptors": {"METHODS": ("GET", "POST"), - "": {"METHODS": ("GET", "DELETE"), "TODO": "PATCH", + "": {"METHODS": ("GET", "DELETE", "PATCH"), "nsd_content": {"METHODS": ("GET", "PUT")}, "nsd": {"METHODS": "GET"}, # descriptor inside package "artifacts": {"*": {"METHODS": "GET"}} @@ -426,7 +444,8 @@ class Server(object): elif "application/yaml" in accept or "*/*" in accept or "text/plain" in accept: pass - else: + # if there is not any valid accept, raise an error. But if response is already an error, format in yaml + elif cherrypy.response.status >= 400: raise cherrypy.HTTPError(HTTPStatus.NOT_ACCEPTABLE.value, "Only 'Accept' of type 'application/json' or 'application/yaml' " "for output format are available") @@ -526,7 +545,7 @@ class Server(object): def test(self, *args, **kwargs): thread_info = None if args and args[0] == "help": - return "
\ninit\nfile/  download file\ndb-clear/table\nprune\nlogin\nlogin2\n"\
+            return "
\ninit\nfile/  download file\ndb-clear/table\nfs-clear[/folder]\nlogin\nlogin2\n"\
                    "sleep/
" elif args and args[0] == "init": @@ -547,9 +566,16 @@ class Server(object): return f elif len(args) == 2 and args[0] == "db-clear": - return self.engine.db.del_list(args[1], kwargs) - elif args and args[0] == "prune": - return self.engine.prune() + deleted_info = self.engine.db.del_list(args[1], kwargs) + return "{} {} deleted\n".format(deleted_info["deleted"], args[1]) + elif len(args) and args[0] == "fs-clear": + if len(args) >= 2: + folders = (args[1],) + else: + folders = self.engine.fs.dir_ls(".") + for folder in folders: + self.engine.fs.file_delete(folder) + return ",".join(folders) + " folders deleted\n" elif args and args[0] == "login": if not cherrypy.request.headers.get("Authorization"): cherrypy.response.headers["WWW-Authenticate"] = 'Basic realm="Access to OSM site", charset="UTF-8"' @@ -596,7 +622,7 @@ class Server(object): " session: {}\n".format(cherrypy.session) + " 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')) + " body:\n") return_text += " length: {}\n".format(cherrypy.request.body.length) if cherrypy.request.body.length: @@ -661,7 +687,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"): + if main_topic not in ("admin", "vnfpkgm", "nsd", "nslcm", "pdu", "nst", "nsilcm"): raise NbiException("URL main_topic '{}' not supported".format(main_topic), HTTPStatus.METHOD_NOT_ALLOWED) if version != 'v1': @@ -675,9 +701,7 @@ class Server(object): force = kwargs.pop("FORCE") else: force = False - self._check_valid_url_method(method, main_topic, version, topic, _id, item, *args) - if main_topic == "admin" and topic == "tokens": return self.token(method, _id, kwargs) @@ -705,7 +729,7 @@ class Server(object): 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 @@ -758,14 +782,14 @@ class Server(object): outdata = {"id": _id} cherrypy.response.status = HTTPStatus.ACCEPTED.value elif topic == "netslice_instances_content": - # creates NSI + # creates NetSlice_Instance_record (NSIR) _id = self.engine.new_item(rollback, session, engine_topic, indata, kwargs, force=force) - # creates nsilcmop + self._set_location_header(main_topic, version, topic, _id) indata["lcmOperationType"] = "instantiate" indata["nsiInstanceId"] = _id - self.engine.new_item(rollback, session, "nsilcmops", indata, None) - self._set_location_header(main_topic, version, topic, _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 @@ -827,13 +851,14 @@ class Server(object): raise NbiException("Method {} not allowed".format(method), HTTPStatus.METHOD_NOT_ALLOWED) return self._format_out(outdata, session, _format) except Exception as e: - if isinstance(e, (NbiException, EngineException, DbException, FsException, MsgException, AuthException)): + if isinstance(e, (NbiException, EngineException, DbException, FsException, MsgException, AuthException, + ValidationError)): 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)) + cherrypy.log("CRITICAL: Exception {}".format(e), traceback=True) http_code_name = HTTPStatus.BAD_REQUEST.name if hasattr(outdata, "close"): # is an open file outdata.close()