X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fengine.py;h=e7bf7c9e9f23eb726e6574e164114b941bf00364;hp=a15420f051560f9809e19483aef12c7a64fc895e;hb=refs%2Fchanges%2F79%2F5979%2F1;hpb=f27c79b67671934005fa1691158c363e2b686e77 diff --git a/osm_nbi/engine.py b/osm_nbi/engine.py index a15420f..e7bf7c9 100644 --- a/osm_nbi/engine.py +++ b/osm_nbi/engine.py @@ -18,6 +18,7 @@ from msgbase import MsgException from http import HTTPStatus from time import time from copy import deepcopy +from validation import validate_input, ValidationError __author__ = "Alfonso Tierno " @@ -276,6 +277,11 @@ class Engine(object): elif item == "nsrs": pass + elif item == "vims" or item == "sdns": + if self.db.get_one(item, {"name": indata.get("name")}, fail_on_empty=False, fail_on_more=False): + raise EngineException("name '{}' already exist for {}".format(indata["name"], item), + HTTPStatus.CONFLICT) + def _format_new_data(self, session, item, indata, admin=None): now = time() @@ -306,6 +312,9 @@ class Engine(object): indata["_admin"]["onboardingState"] = "CREATED" indata["_admin"]["operationalState"] = "DISABLED" indata["_admin"]["usageSate"] = "NOT_IN_USE" + elif item in ("vims", "sdns"): + indata["_admin"]["operationalState"] = "PROCESSING" + if storage: indata["_admin"]["storage"] = storage indata["_id"] = _id @@ -500,25 +509,14 @@ class Engine(object): Creates a new entry into database. For nsds and vnfds it creates an almost empty DISABLED entry, that must be completed with a call to method upload_content :param session: contains the used login username and working project - :param item: it can be: users, projects, nsrs, nsds, vnfds + :param item: it can be: users, projects, vims, sdns, nsrs, nsds, vnfds :param indata: data to be inserted :param kwargs: used to override the indata descriptor :param headers: http request headers :return: _id, transaction_id: identity of the inserted data. or transaction_id if Content-Range is used """ - # TODO validate input. Check not exist at database - # TODO add admin and status transaction = None - # if headers.get("Content-Range") or "application/gzip" in headers.get("Content-Type") or \ - # "application/x-gzip" in headers.get("Content-Type") or "application/zip" in headers.get("Content-Type") or \ - # "text/plain" in headers.get("Content-Type"): - # if not indata: - # raise EngineException("Empty payload") - # transaction = self._new_item_partial(session, item, indata, headers) - # if "desc" not in transaction: - # return transaction["_id"], False - # indata = transaction["desc"] item_envelop = item if item in ("nsds", "vnfds"): @@ -552,6 +550,11 @@ class Engine(object): except IndexError: raise EngineException( "Invalid query string '{}'. Index '{}' out of range".format(k, kitem_old)) + try: + validate_input(content, item, new=True) + except ValidationError as e: + raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY) + if not indata and item not in ("nsds", "vnfds"): raise EngineException("Empty payload") @@ -568,6 +571,14 @@ class Engine(object): _id = self.db.create(item, content) if item == "nsrs": self.msg.write("ns", "create", _id) + elif item == "vims": + msg_data = self.db.get_one(item, {"_id": _id}) + msg_data.pop("_admin", None) + self.msg.write("vim_account", "create", msg_data) + elif item == "sdns": + msg_data = self.db.get_one(item, {"_id": _id}) + msg_data.pop("_admin", None) + self.msg.write("sdn", "create", msg_data) return _id def _add_read_filter(self, session, item, filter): @@ -645,7 +656,6 @@ class Engine(object): "", http_code=HTTPStatus.NOT_ACCEPTABLE) return self.fs.file_open((storage['folder'], storage['zipfile']), "rb"), "application/zip" - def get_item_list(self, session, item, filter={}): """ Get a list of items @@ -701,17 +711,20 @@ class Engine(object): filter = {"_id": _id} self._add_delete_filter(session, item, filter) - if item == "nsrs": + if item in ("nsrs", "vims", "sdns"): desc = self.db.get_one(item, filter) desc["_admin"]["to_delete"] = True self.db.replace(item, _id, desc) # TODO change to set_one - self.msg.write("ns", "delete", _id) - return {"deleted": 1} + if item == "nsrs": + self.msg.write("ns", "delete", _id) + elif item == "vims": + self.msg.write("vim_account", "delete", {"_id": _id}) + elif item == "sdns": + self.msg.write("sdn", "delete", {"_id": _id}) + return {"deleted": 1} # TODO indicate an offline operation to return 202 ACCEPTED v = self.db.del_one(item, filter) self.fs.file_delete(_id, ignore_non_exist=True) - if item == "nsrs": - self.msg.write("ns", "delete", _id) return v def prune(self): @@ -723,18 +736,47 @@ class Engine(object): def create_admin(self): """ - Creates a new user admin/admin into database. Only allowed if database is empty. Useful for initialization - :return: _id identity of the inserted data. + Creates a new user admin/admin into database if database is empty. Useful for initialization + :return: _id identity of the inserted data, or None """ users = self.db.get_one("users", fail_on_empty=False, fail_on_more=False) if users: - raise EngineException("Unauthorized. Database users is not empty", HTTPStatus.UNAUTHORIZED) + return None + # raise EngineException("Unauthorized. Database users is not empty", HTTPStatus.UNAUTHORIZED) indata = {"username": "admin", "password": "admin", "projects": ["admin"]} fake_session = {"project_id": "admin", "username": "admin"} self._format_new_data(fake_session, "users", indata) _id = self.db.create("users", indata) return _id + def init_db(self, target_version='1.0'): + """ + Init database if empty. If not empty it checks that database version is ok. + If empty, it creates a new user admin/admin at 'users' and a new entry at 'version' + :return: None if ok, exception if error or if the version is different. + """ + version = self.db.get_one("version", fail_on_empty=False, fail_on_more=False) + if not version: + # create user admin + self.create_admin() + # create database version + version_data = { + "_id": '1.0', # version text + "version": 1000, # version number + "date": "2018-04-12", # version date + "description": "initial design", # changes in this version + 'status': 'ENABLED' # ENABLED, DISABLED (migration in process), ERROR, + } + self.db.create("version", version_data) + elif version["_id"] != target_version: + # TODO implement migration process + raise EngineException("Wrong database version '{}'. Expected '{}'".format( + version["_id"], target_version), HTTPStatus.INTERNAL_SERVER_ERROR) + elif version["status"] != 'ENABLED': + raise EngineException("Wrong database status '{}'".format( + version["status"]), HTTPStatus.INTERNAL_SERVER_ERROR) + return + def _edit_item(self, session, item, id, content, indata={}, kwargs=None): if indata: indata = self._remove_envelop(item, indata) @@ -766,11 +808,22 @@ class Engine(object): except IndexError: raise EngineException( "Invalid query string '{}'. Index '{}' out of range".format(k, kitem_old)) + try: + validate_input(content, item, new=False) + except ValidationError as e: + raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY) _deep_update(content, indata) self._validate_new_data(session, item, content, id) # self._format_new_data(session, item, content) self.db.replace(item, id, content) + if item in ("vims", "sdns"): + indata.pop("_admin", None) + indata["_id"] = id + if item == "vims": + self.msg.write("vim_account", "edit", indata) + elif item == "sdns": + self.msg.write("sdn", "edit", indata) return id def edit_item(self, session, item, _id, indata={}, kwargs=None):