From 55ba2e6f758ae650a2dbbc20638c0108df726809 Mon Sep 17 00:00:00 2001 From: tierno Date: Tue, 11 Dec 2018 17:22:22 +0000 Subject: [PATCH] Feature 5945 Adding WIM to NBI Change-Id: Ifaf1c057d94d9208be5cabc97f1ae6d5c74ae5a2 Signed-off-by: tierno --- osm_nbi/admin_topics.py | 65 +++++++++++++++++++++++++++++++++++++ osm_nbi/engine.py | 3 +- osm_nbi/html_out.py | 1 + osm_nbi/html_public/version | 4 +-- osm_nbi/nbi.py | 9 +++-- osm_nbi/tests/clear-all.sh | 4 ++- osm_nbi/tests/test.py | 27 ++++++++++++++- osm_nbi/validation.py | 40 +++++++++++++++++++++-- 8 files changed, 144 insertions(+), 9 deletions(-) diff --git a/osm_nbi/admin_topics.py b/osm_nbi/admin_topics.py index b1c9ac7..afa50d8 100644 --- a/osm_nbi/admin_topics.py +++ b/osm_nbi/admin_topics.py @@ -19,6 +19,7 @@ from hashlib import sha256 from http import HTTPStatus from validation import user_new_schema, user_edit_schema, project_new_schema, project_edit_schema from validation import vim_account_new_schema, vim_account_edit_schema, sdn_new_schema, sdn_edit_schema +from validation import wim_account_new_schema, wim_account_edit_schema from base_topic import BaseTopic, EngineException __author__ = "Alfonso Tierno " @@ -200,6 +201,70 @@ class VimAccountTopic(BaseTopic): return v # TODO indicate an offline operation to return 202 ACCEPTED +class WimAccountTopic(BaseTopic): + topic = "wim_accounts" + topic_msg = "wim_account" + schema_new = wim_account_new_schema + schema_edit = wim_account_edit_schema + wim_config_encrypted = () + + def __init__(self, db, fs, msg): + BaseTopic.__init__(self, db, fs, msg) + + def check_conflict_on_new(self, session, indata, force=False): + self.check_unique_name(session, indata["name"], _id=None) + + def check_conflict_on_edit(self, session, final_content, edit_content, _id, force=False): + if not force and edit_content.get("name"): + self.check_unique_name(session, edit_content["name"], _id=_id) + + # encrypt passwords + schema_version = final_content.get("schema_version") + if schema_version: + if edit_content.get("wim_password"): + final_content["wim_password"] = self.db.encrypt(edit_content["wim_password"], + schema_version=schema_version, salt=_id) + if edit_content.get("config"): + for p in self.wim_config_encrypted: + if edit_content["config"].get(p): + final_content["config"][p] = self.db.encrypt(edit_content["config"][p], + schema_version=schema_version, salt=_id) + + def format_on_new(self, content, project_id=None, make_public=False): + BaseTopic.format_on_new(content, project_id=project_id, make_public=make_public) + content["schema_version"] = schema_version = "1.1" + + # encrypt passwords + if content.get("wim_password"): + content["wim_password"] = self.db.encrypt(content["wim_password"], schema_version=schema_version, + salt=content["_id"]) + if content.get("config"): + for p in self.wim_config_encrypted: + if content["config"].get(p): + content["config"][p] = self.db.encrypt(content["config"][p], schema_version=schema_version, + salt=content["_id"]) + + content["_admin"]["operationalState"] = "PROCESSING" + + def delete(self, session, _id, force=False, dry_run=False): + """ + Delete item by its internal _id + :param session: contains the used login username, working project, and admin rights + :param _id: server internal id + :param force: indicates if deletion must be forced in case of conflict + :param dry_run: make checking but do not delete + :return: dictionary with deleted item _id. It raises EngineException on error: not found, conflict, ... + """ + # TODO add admin to filter, validate rights + if dry_run or force: # delete completely + return BaseTopic.delete(self, session, _id, force, dry_run) + else: # if not, sent to kafka + v = BaseTopic.delete(self, session, _id, force, dry_run=True) + self.db.set_one("wim_accounts", {"_id": _id}, {"_admin.to_delete": True}) # TODO change status + self._send_msg("delete", {"_id": _id}) + return v # TODO indicate an offline operation to return 202 ACCEPTED + + class SdnTopic(BaseTopic): topic = "sdns" topic_msg = "sdn" diff --git a/osm_nbi/engine.py b/osm_nbi/engine.py index 14dab56..38cc08e 100644 --- a/osm_nbi/engine.py +++ b/osm_nbi/engine.py @@ -20,7 +20,7 @@ from osm_common.fsbase import FsException from osm_common.msgbase import MsgException from http import HTTPStatus from base_topic import EngineException, versiontuple -from admin_topics import UserTopic, ProjectTopic, VimAccountTopic, SdnTopic +from admin_topics import UserTopic, ProjectTopic, VimAccountTopic, WimAccountTopic, SdnTopic from descriptor_topics import VnfdTopic, NsdTopic, PduTopic, NstTopic from instance_topics import NsrTopic, VnfrTopic, NsLcmOpTopic, NsiTopic, NsiLcmOpTopic from base64 import b64encode @@ -40,6 +40,7 @@ class Engine(object): "vnfrs": VnfrTopic, "nslcmops": NsLcmOpTopic, "vim_accounts": VimAccountTopic, + "wim_accounts": WimAccountTopic, "sdns": SdnTopic, "users": UserTopic, "projects": ProjectTopic, diff --git a/osm_nbi/html_out.py b/osm_nbi/html_out.py index 94793ac..6f07d71 100644 --- a/osm_nbi/html_out.py +++ b/osm_nbi/html_out.py @@ -44,6 +44,7 @@ html_start = """ PROJECTs TOKENs VIMs + WIMs SDNs logout diff --git a/osm_nbi/html_public/version b/osm_nbi/html_public/version index 279998e..1b5afc2 100644 --- a/osm_nbi/html_public/version +++ b/osm_nbi/html_public/version @@ -1,2 +1,2 @@ -0.1.30 -2018-12-05 +0.1.31 +2018-12-12 diff --git a/osm_nbi/nbi.py b/osm_nbi/nbi.py index 2dfeb22..3dd3348 100644 --- a/osm_nbi/nbi.py +++ b/osm_nbi/nbi.py @@ -101,7 +101,9 @@ URL: /osm GET POST / O O O O /projects O O / O O - /vims_accounts (also vims for compatibility) O O + /vim_accounts (also vims for compatibility) O O + / O O O + /wim_accounts O O / O O O /sdns O O / O O O @@ -214,6 +216,9 @@ class Server(object): "vim_accounts": {"METHODS": ("GET", "POST"), "": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")} }, + "wim_accounts": {"METHODS": ("GET", "POST"), + "": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")} + }, "sdns": {"METHODS": ("GET", "POST"), "": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")} }, @@ -831,7 +836,7 @@ class Server(object): else: self.engine.del_item(session, engine_topic, _id, force) cherrypy.response.status = HTTPStatus.NO_CONTENT.value - if engine_topic in ("vim_accounts", "sdns"): + if engine_topic in ("vim_accounts", "wim_accounts", "sdns"): cherrypy.response.status = HTTPStatus.ACCEPTED.value elif method in ("PUT", "PATCH"): diff --git a/osm_nbi/tests/clear-all.sh b/osm_nbi/tests/clear-all.sh index 9b6b8c6..4bcd7f0 100755 --- a/osm_nbi/tests/clear-all.sh +++ b/osm_nbi/tests/clear-all.sh @@ -80,7 +80,7 @@ then done fi -for item in vim_accounts sdns nsrs vnfrs nslcmops nsds vnfds projects pdus nsts nsis nsilcmops # vims +for item in vim_accounts wim_accounts sdns nsrs vnfrs nslcmops nsds vnfds projects pdus nsts nsis nsilcmops # vims do curl --insecure ${OSMNBI_URL}/test/db-clear/${item} done @@ -98,6 +98,8 @@ then for dc in `openmano datacenter-list | awk '{print $1}'` ; do openmano datacenter-detach $dc ; done for dc in `openmano datacenter-list --all | awk '{print $1}'` ; do openmano datacenter-delete -f $dc ; done for dc in `openmano sdn-controller-list | awk '{print $1}'` ; do openmano sdn-controller-delete -f $dc ; done + for dc in `openmano wim-list | awk '{print $1}'` ; do openmano wim-detach $dc ; done + for dc in `openmano wim-list --all | awk '{print $1}'` ; do openmano wim-delete -f $dc ; done fi if [ -n "$OSMNBI_CLEAN_VCA" ] diff --git a/osm_nbi/tests/test.py b/osm_nbi/tests/test.py index 389d14b..a0b1eb0 100755 --- a/osm_nbi/tests/test.py +++ b/osm_nbi/tests/test.py @@ -355,7 +355,8 @@ class TestRest: wait = timeout_delete while wait >= 0: - r = self.test(description, "GET", url, headers_yaml, (200, 404), None, r_header_yaml, "yaml", pooling=True) + r = self.test(description, "GET", url_op, headers_yaml, None, (200, 404), None, r_header_yaml, "yaml", + pooling=True) if not r: return if r.status_code == 404: @@ -609,6 +610,17 @@ class TestVIMSDN(TestFakeVim): def __init__(self): TestFakeVim.__init__(self) + self.wim = { + "schema_version": "1.0", + "schema_type": "No idea", + "name": "myWim", + "description": "Descriptor name", + "wim_type": "odl", + "wim_url": "http://localhost:/wim", + "user": "user", + "password": "password", + "config": {"config_param": 1} + } def run(self, engine, test_osm, manual_check, test_params=None): engine.set_test_name("VimSdn") @@ -635,6 +647,10 @@ class TestVIMSDN(TestFakeVim): engine.test("Edit VIM remove port-mapping", "PUT", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json, {"config": {"sdn-port-mapping": None}}, 204, None, None) + engine.test("Create WIM", "POST", "/admin/v1/wim_accounts", headers_json, self.wim, (200, 204, 201), + {"Location": "/admin/v1/wim_accounts/", "Content-Type": "application/json"}, "json"), + wim_id = engine.last_id + if not test_osm: # delete with FORCE engine.test("Delete VIM remove port-mapping", "DELETE", @@ -642,18 +658,27 @@ class TestVIMSDN(TestFakeVim): engine.test("Delete SDNC", "DELETE", "/admin/v1/sdns/{}?FORCE=True".format(sdnc_id), headers_json, None, 202, None, 0) + engine.test("Delete WIM", "DELETE", + "/admin/v1/wim_accounts/{}?FORCE=True".format(wim_id), headers_json, None, 202, None, 0) engine.test("Check VIM is deleted", "GET", "/admin/v1/vim_accounts/{}".format(vim_id), headers_yaml, None, 404, r_header_yaml, "yaml") engine.test("Check SDN is deleted", "GET", "/admin/v1/sdns/{}".format(sdnc_id), headers_yaml, None, 404, r_header_yaml, "yaml") + engine.test("Check WIM is deleted", "GET", "/admin/v1/wim_accounts/{}".format(wim_id), headers_yaml, + None, 404, r_header_yaml, "yaml") else: + if manual_check: + input('VIM, SDN, WIM has been deployed. Perform manual check and press enter to resume') # delete and wait until is really deleted engine.test("Delete VIM remove port-mapping", "DELETE", "/admin/v1/vim_accounts/{}".format(vim_id), headers_json, None, (202, 201, 204), None, 0) engine.test("Delete SDN", "DELETE", "/admin/v1/sdns/{}".format(sdnc_id), headers_json, None, (202, 201, 204), None, 0) + engine.test("Delete VIM", "DELETE", "/admin/v1/wim_accounts/{}".format(wim_id), + headers_json, None, (202, 201, 204), None, 0) engine.wait_until_delete("/admin/v1/vim_accounts/{}".format(vim_id), timeout) engine.wait_until_delete("/admin/v1/sdns/{}".format(sdnc_id), timeout) + engine.wait_until_delete("/admin/v1/wim_accounts/{}".format(wim_id), timeout) class TestDeploy: diff --git a/osm_nbi/validation.py b/osm_nbi/validation.py index fd4e0e5..bb966e2 100644 --- a/osm_nbi/validation.py +++ b/osm_nbi/validation.py @@ -325,6 +325,7 @@ ns_scale = { # TODO for the moment it is only VDU-scaling schema_version = {"type": "string", "enum": ["1.0"]} +schema_type = {"type": "string"} vim_account_edit_schema = { "title": "vim_account edit input schema", "$schema": "http://json-schema.org/draft-04/schema#", @@ -332,7 +333,7 @@ vim_account_edit_schema = { "properties": { "name": name_schema, "description": description_schema, - "type": nameshort_schema, # currently "openvim" or "openstack", can be enlarged with plugins + "type": nameshort_schema, "vim": name_schema, "datacenter": name_schema, "vim_url": description_schema, @@ -345,7 +346,6 @@ vim_account_edit_schema = { }, "additionalProperties": False } -schema_type = {"type": "string"} vim_account_new_schema = { "title": "vim_account creation input schema", @@ -371,6 +371,42 @@ vim_account_new_schema = { "additionalProperties": False } +wim_account_edit_schema = { + "title": "wim_account edit input schema", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "name": name_schema, + "description": description_schema, + "type": nameshort_schema, + "wim": name_schema, + "wim_url": description_schema, + "user": nameshort_schema, + "password": passwd_schema, + "config": {"type": "object"} + }, + "additionalProperties": False +} + +wim_account_new_schema = { + "title": "wim_account creation input schema", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "schema_version": schema_version, + "schema_type": schema_type, + "name": name_schema, + "description": description_schema, + "wim": name_schema, + "wim_type": {"enum": ["tapi", "onos", "odl", "dynpac"]}, + "wim_url": description_schema, + "user": nameshort_schema, + "password": passwd_schema, + "config": {"type": "object"} + }, + "required": ["name", "wim_url", "wim_type"], + "additionalProperties": False +} sdn_properties = { "name": name_schema, -- 2.17.1