Feature 5945 Adding WIM to NBI 52/7052/4
authortierno <alfonso.tiernosepulveda@telefonica.com>
Tue, 11 Dec 2018 17:22:22 +0000 (17:22 +0000)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Thu, 13 Dec 2018 10:12:51 +0000 (10:12 +0000)
Change-Id: Ifaf1c057d94d9208be5cabc97f1ae6d5c74ae5a2
Signed-off-by: tierno <alfonso.tiernosepulveda@telefonica.com>
osm_nbi/admin_topics.py
osm_nbi/engine.py
osm_nbi/html_out.py
osm_nbi/html_public/version
osm_nbi/nbi.py
osm_nbi/tests/clear-all.sh
osm_nbi/tests/test.py
osm_nbi/validation.py

index b1c9ac7..afa50d8 100644 (file)
@@ -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 <alfonso.tiernosepulveda@telefonica.com>"
@@ -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"
index 14dab56..38cc08e 100644 (file)
@@ -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,
index 94793ac..6f07d71 100644 (file)
@@ -44,6 +44,7 @@ html_start = """
       <a href="/osm/admin/v1/projects">PROJECTs </a>
       <a href="/osm/admin/v1/tokens">TOKENs </a>
       <a href="/osm/admin/v1/vim_accounts">VIMs </a>
+      <a href="/osm/admin/v1/wim_accounts">WIMs </a>
       <a href="/osm/admin/v1/sdns">SDNs </a>
       <a href="/osm/admin/v1/tokens?METHOD=DELETE">logout </a>
     </div>
index 279998e..1b5afc2 100644 (file)
@@ -1,2 +1,2 @@
-0.1.30
-2018-12-05
+0.1.31
+2018-12-12
index 2dfeb22..3dd3348 100644 (file)
@@ -101,7 +101,9 @@ URL: /osm                                                       GET     POST
                 /<id>                                           O               O       O       O
             /projects                                           O       O
                 /<id>                                           O                       O
-            /vims_accounts  (also vims for compatibility)       O       O
+            /vim_accounts  (also vims for compatibility)        O       O
+                /<id>                                           O                       O       O
+            /wim_accounts                                       O       O
                 /<id>                                           O                       O       O
             /sdns                                               O       O
                 /<id>                                           O                       O       O
@@ -214,6 +216,9 @@ class Server(object):
                     "vim_accounts": {"METHODS": ("GET", "POST"),
                                      "<ID>": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")}
                                      },
+                    "wim_accounts": {"METHODS": ("GET", "POST"),
+                                     "<ID>": {"METHODS": ("GET", "DELETE", "PATCH", "PUT")}
+                                     },
                     "sdns": {"METHODS": ("GET", "POST"),
                              "<ID>": {"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"):
index 9b6b8c6..4bcd7f0 100755 (executable)
@@ -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" ]
index 389d14b..a0b1eb0 100755 (executable)
@@ -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:
index fd4e0e5..bb966e2 100644 (file)
@@ -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,