Added more instantitaion parameters and check input 26/6326/5
authortierno <alfonso.tiernosepulveda@telefonica.com>
Tue, 10 Jul 2018 10:52:48 +0000 (12:52 +0200)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Tue, 17 Jul 2018 13:06:14 +0000 (15:06 +0200)
Change-Id: Ic3a9e876fb57a1f04f835ecb8a9fcaeeb5089ad3
Signed-off-by: tierno <alfonso.tiernosepulveda@telefonica.com>
osm_nbi/engine.py
osm_nbi/html_public/version
osm_nbi/validation.py

index aaa94f0..1ffa616 100644 (file)
@@ -17,7 +17,7 @@ from osm_common.fsbase import FsException
 from osm_common.msgbase import MsgException
 from http import HTTPStatus
 from time import time
 from osm_common.msgbase import MsgException
 from http import HTTPStatus
 from time import time
-from copy import deepcopy
+from copy import deepcopy, copy
 from validation import validate_input, ValidationError
 
 __author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
 from validation import validate_input, ValidationError
 
 __author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
@@ -53,6 +53,17 @@ def _deep_update(dict_to_change, dict_reference):
             _deep_update(dict_to_change[k], dict_reference[k])
 
 
             _deep_update(dict_to_change[k], dict_reference[k])
 
 
+def get_iterable(input):
+    """
+    Returns an iterable, in case input is None it just returns an empty tuple
+    :param input:
+    :return: iterable
+    """
+    if input is None:
+        return ()
+    return input
+
+
 class Engine(object):
 
     def __init__(self):
 class Engine(object):
 
     def __init__(self):
@@ -342,22 +353,108 @@ class Engine(object):
         :param indata: descriptor with the parameters of the operation
         :return: None
         """
         :param indata: descriptor with the parameters of the operation
         :return: None
         """
+        vnfds = {}
+        vim_accounts = []
+        nsd = nsr["nsd"]
+
         def check_valid_vnf_member_index(member_vnf_index):
         def check_valid_vnf_member_index(member_vnf_index):
-            for vnf in nsr["nsd"]["constituent-vnfd"]:
+            for vnf in nsd["constituent-vnfd"]:
                 if member_vnf_index == vnf["member-vnf-index"]:
                 if member_vnf_index == vnf["member-vnf-index"]:
-                    break
+                    vnfd_id = vnf["vnfd-id-ref"]
+                    if vnfd_id not in vnfds:
+                        vnfds[vnfd_id] = self.db.get_one("vnfds", {"id": vnfd_id})
+                    return vnfds[vnfd_id]
             else:
                 raise EngineException("Invalid parameter member_vnf_index='{}' is not one of the "
                                       "nsd:constituent-vnfd".format(member_vnf_index))
 
             else:
                 raise EngineException("Invalid parameter member_vnf_index='{}' is not one of the "
                                       "nsd:constituent-vnfd".format(member_vnf_index))
 
+        def check_valid_vim_account(vim_account):
+            if vim_account in vim_accounts:
+                return
+            try:
+                self.db.get_one("vim_accounts", {"_id": vim_account})
+            except Exception:
+                raise EngineException("Invalid vimAccountId='{}' not present".format(vim_account))
+            vim_accounts.append(vim_account)
+
         if operation == "action":
         if operation == "action":
+            # check vnf_member_index
             if indata.get("vnf_member_index"):
                 indata["member_vnf_index"] = indata.pop("vnf_member_index")    # for backward compatibility
             if indata.get("vnf_member_index"):
                 indata["member_vnf_index"] = indata.pop("vnf_member_index")    # for backward compatibility
-            check_valid_vnf_member_index(indata["member_vnf_index"])
-            # TODO get vnfd, check primitives
+            if not indata.get("member_vnf_index"):
+                raise EngineException("Missing 'member_vnf_index' parameter")
+            vnfd = check_valid_vnf_member_index(indata["member_vnf_index"])
+            # check primitive
+            for config_primitive in get_iterable(vnfd.get("vnf-configuration", {}).get("config-primitive")):
+                if indata["primitive"] == config_primitive["name"]:
+                    # check needed primitive_params are provided
+                    if indata.get("primitive_params"):
+                        in_primitive_params_copy = copy(indata["primitive_params"])
+                    else:
+                        in_primitive_params_copy = {}
+                    for paramd in get_iterable(config_primitive.get("parameter")):
+                        if paramd["name"] in in_primitive_params_copy:
+                            del in_primitive_params_copy[paramd["name"]]
+                        elif not paramd.get("default-value"):
+                            raise EngineException("Needed parameter {} not provided for primitive '{}'".format(
+                                paramd["name"], indata["primitive"]))
+                    # check no extra primitive params are provided
+                    if in_primitive_params_copy:
+                        raise EngineException("parameter/s '{}' not present at vnfd for primitive '{}'".format(
+                            list(in_primitive_params_copy.keys()), indata["primitive"]))
+                    break
+            else:
+                raise EngineException("Invalid primitive '{}' is not present at vnfd".format(indata["primitive"]))
         if operation == "scale":
         if operation == "scale":
-            check_valid_vnf_member_index(indata["scaleVnfData"]["scaleByStepData"]["member-vnf-index"])
-            # TODO check vnf scaling primitives
+            vnfd = check_valid_vnf_member_index(indata["scaleVnfData"]["scaleByStepData"]["member-vnf-index"])
+            for scaling_group in get_iterable(vnfd.get("scaling-group-descriptor")):
+                if indata["scaleVnfData"]["scaleByStepData"]["scaling-group-descriptor"] == scaling_group["name"]:
+                    break
+            else:
+                raise EngineException("Invalid scaleVnfData:scaleByStepData:scaling-group-descriptor '{}' is not "
+                                      "present at vnfd:scaling-group-descriptor".format(
+                                          indata["scaleVnfData"]["scaleByStepData"]["scaling-group-descriptor"]))
+        if operation == "instantiate":
+            # check vim_account
+            check_valid_vim_account(indata["vimAccountId"])
+            for in_vnf in get_iterable(indata.get("vnf")):
+                vnfd = check_valid_vnf_member_index(in_vnf["member-vnf-index"])
+                if in_vnf.get("vimAccountId"):
+                    check_valid_vim_account(in_vnf["vimAccountId"])
+                for in_vdu in get_iterable(in_vnf.get("vdu")):
+                    for vdud in get_iterable(vnfd.get("vdu")):
+                        if vdud["id"] == in_vdu["id"]:
+                            for volume in get_iterable(in_vdu.get("volume")):
+                                for volumed in get_iterable(vdud.get("volumes")):
+                                    if volumed["name"] == volume["name"]:
+                                        break
+                                else:
+                                    raise EngineException("Invalid parameter vnf[member-vnf-index='{}']:vdu[id='{}']:"
+                                                          "volume:name='{}' is not present at vnfd:vdu:volumes list".
+                                                          format(in_vnf["member-vnf-index"], in_vdu["id"],
+                                                                 volume["name"]))
+                            break
+                    else:
+                        raise EngineException("Invalid parameter vnf[member-vnf-index='{}']:vdu:id='{}' is not "
+                                              "present at vnfd".format(in_vnf["member-vnf-index"], in_vdu["id"]))
+
+                for in_internal_vld in get_iterable(in_vnf.get("internal-vld")):
+                    for internal_vldd in get_iterable(vnfd.get("internal-vld")):
+                        if in_internal_vld["name"] == internal_vldd["name"] or \
+                                in_internal_vld["name"] == internal_vldd["id"]:
+                            break
+                    else:
+                        raise EngineException("Invalid parameter vnf[member-vnf-index='{}']:internal-vld:name='{}'"
+                                              " is not present at vnfd '{}'".format(in_vnf["member-vnf-index"],
+                                                                                    in_internal_vld["name"],
+                                                                                    vnfd["id"]))
+            for in_vld in get_iterable(indata.get("vld")):
+                for vldd in get_iterable(nsd.get("vld")):
+                    if in_vld["name"] == vldd["name"] or in_vld["name"] == vldd["id"]:
+                            break
+                    else:
+                        raise EngineException("Invalid parameter vld:name='{}' is not present at nsd:vld".format(
+                            in_vld["name"]))
 
     def _format_new_data(self, session, item, indata):
         now = time()
 
     def _format_new_data(self, session, item, indata):
         now = time()
index e2b889d..85e4884 100644 (file)
@@ -1,3 +1,3 @@
-0.1.13
-2018-07-03
+0.1.14
+2018-07-10
 
 
index cb249ba..29c069b 100644 (file)
@@ -18,8 +18,9 @@ name_schema = {"type": "string", "minLength": 1, "maxLength": 255, "pattern": "^
 string_schema = {"type": "string", "minLength": 1, "maxLength": 255}
 xml_text_schema = {"type": "string", "minLength": 1, "maxLength": 1000, "pattern": "^[^']+$"}
 description_schema = {"type": ["string", "null"], "maxLength": 255, "pattern": "^[^'\"]+$"}
 string_schema = {"type": "string", "minLength": 1, "maxLength": 255}
 xml_text_schema = {"type": "string", "minLength": 1, "maxLength": 1000, "pattern": "^[^']+$"}
 description_schema = {"type": ["string", "null"], "maxLength": 255, "pattern": "^[^'\"]+$"}
-id_schema_fake = {"type": "string", "minLength": 2,
-                  "maxLength": 36}
+id_schema_fake = {"type": "string", "minLength": 2, "maxLength": 36}
+bool_schema = {"type": "boolean"}
+null_schema = {"type": "null"}
 # "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
 id_schema = {"type": "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
 time_schema = {"type": "string", "pattern": "^[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]([0-5]:){2}"}
 # "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
 id_schema = {"type": "string", "pattern": "^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"}
 time_schema = {"type": "string", "pattern": "^[0-9]{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]([0-5]:){2}"}
@@ -48,6 +49,122 @@ log_level_schema = {"type": "string", "enum": ["DEBUG", "INFO", "WARNING", "ERRO
 checksum_schema = {"type": "string", "pattern": "^[0-9a-fA-F]{32}$"}
 size_schema = {"type": "integer", "minimum": 1, "maximum": 100}
 
 checksum_schema = {"type": "string", "pattern": "^[0-9a-fA-F]{32}$"}
 size_schema = {"type": "integer", "minimum": 1, "maximum": 100}
 
+ns_instantiate_vdu = {
+    "title": "ns action instantiate input schema for vdu",
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "type": "object",
+    "properties": {
+        "id": name_schema,
+        "volume": {
+            "type": "array",
+            "minItems": 1,
+            "items": {
+                "type": "object",
+                "properties": {
+                    "name": name_schema,
+                    "vim-volume-id": name_schema,
+                },
+                "required": ["name", "vim-volume-id"],
+                "additionalProperties": False
+            }
+        },
+        "interface": {
+            "type": "array",
+            "minItems": 1,
+            "items": {
+                "type": "object",
+                "properties": {
+                    "name": name_schema,
+                    "ip-address": ip_schema,
+                    "mac-address": mac_schema,
+                    "floating-ip-required": bool_schema,
+                },
+                "required": ["name"],
+                "additionalProperties": False
+            }
+        }
+    },
+    "required": ["id"],
+    "additionalProperties": False
+}
+
+ip_profile_dns_schema = {
+    "type": "array",
+    "minItems": 1,
+    "items": {
+        "type": "object",
+        "properties": {
+            "address": ip_schema,
+        },
+        "required": ["address"],
+        "additionalProperties": False
+    }
+}
+
+ip_profile_dhcp_schema = {
+    "type": "object",
+    "properties": {
+        "enabled": {"type": "boolean"},
+        "count": integer1_schema,
+        "start-address": ip_schema
+    },
+    "additionalProperties": False,
+}
+
+ip_profile_schema = {
+    "title": "ip profile validation schame",
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "type": "object",
+    "properties": {
+        "ip-version": {"enum": ["ipv4", "ipv6"]},
+        "subnet-address": ip_prefix_schema,
+        "gateway-address": ip_schema,
+        "dns-server": ip_profile_dns_schema,
+        "dhcp-params": ip_profile_dhcp_schema,
+    }
+}
+
+ip_profile_update_schema = {
+    "title": "ip profile validation schame",
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "type": "object",
+    "properties": {
+        "ip-version": {"enum": ["ipv4", "ipv6"]},
+        "subnet-address": {"oneOf": [null_schema, ip_prefix_schema]},
+        "gateway-address": {"oneOf": [null_schema, ip_schema]},
+        "dns-server": {"oneOf": [null_schema, ip_profile_dns_schema]},
+
+        "dhcp-params": {"oneOf": [null_schema, ip_profile_dhcp_schema]},
+    },
+    "additionalProperties": False
+}
+
+ns_instantiate_internal_vld = {
+    "title": "ns action instantiate input schema for vdu",
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "type": "object",
+    "properties": {
+        "name": name_schema,
+        "vim-network-name": name_schema,
+        "ip-profile": ip_profile_update_schema,
+        "internal-connection-point": {
+            "type": "array",
+            "minItems": 1,
+            "items": {
+                "type": "object",
+                "properties": {
+                    "id-ref": name_schema,
+                    "ip-address": ip_schema,
+                },
+                "required": ["id-ref", "ip-address"],
+                "additionalProperties": False
+            },
+        }
+    },
+    "required": ["name"],
+    "minProperties": 2,
+    "additionalProperties": False
+}
 
 ns_instantiate = {
     "title": "ns action instantiate input schema",
 
 ns_instantiate = {
     "title": "ns action instantiate input schema",
@@ -55,10 +172,11 @@ ns_instantiate = {
     "type": "object",
     "properties": {
         "nsName": name_schema,
     "type": "object",
     "properties": {
         "nsName": name_schema,
-        "nsDescription": description_schema,
+        "nsDescription": {"oneOf": [description_schema, {"type": "null"}]},
         "nsdId": id_schema,
         "vimAccountId": id_schema,
         "ssh_keys": {"type": "string"},
         "nsdId": id_schema,
         "vimAccountId": id_schema,
         "ssh_keys": {"type": "string"},
+        "nsr_id": id_schema,
         "vnf": {
             "type": "array",
             "minItems": 1,
         "vnf": {
             "type": "array",
             "minItems": 1,
@@ -67,8 +185,20 @@ ns_instantiate = {
                 "properties": {
                     "member-vnf-index": name_schema,
                     "vimAccountId": id_schema,
                 "properties": {
                     "member-vnf-index": name_schema,
                     "vimAccountId": id_schema,
+                    "vdu": {
+                        "type": "array",
+                        "minItems": 1,
+                        "items": ns_instantiate_vdu,
+                    },
+                    "internal-vld": {
+                        "type": "array",
+                        "minItems": 1,
+                        "items": ns_instantiate_internal_vld
+                    }
                 },
                 },
-                "required": ["member-vnf-index"]
+                "required": ["member-vnf-index"],
+                "minProperties": 2,
+                "additionalProperties": False
             }
         },
         "vld": {
             }
         },
         "vld": {
@@ -81,11 +211,13 @@ ns_instantiate = {
                     "vim-network-name": {"OneOf": [string_schema, object_schema]},
                     "ip-profile": object_schema,
                 },
                     "vim-network-name": {"OneOf": [string_schema, object_schema]},
                     "ip-profile": object_schema,
                 },
-                "required": ["name"]
+                "required": ["name"],
+                "additionalProperties": False
             }
         },
     },
             }
         },
     },
-    "required": ["nsName", "nsdId", "vimAccountId"]
+    "required": ["nsName", "nsdId", "vimAccountId"],
+    "additionalProperties": False
 }
 
 ns_action = {   # TODO for the moment it is only contemplated the vnfd primitive execution
 }
 
 ns_action = {   # TODO for the moment it is only contemplated the vnfd primitive execution
@@ -284,4 +416,4 @@ def validate_input(indata, item, new=True):
             error_pos = "at '" + ":".join(map(str, e.path)) + "'"
         else:
             error_pos = ""
             error_pos = "at '" + ":".join(map(str, e.path)) + "'"
         else:
             error_pos = ""
-        raise ValidationError("Format error {} '{}' ".format(error_pos, e))
+        raise ValidationError("Format error {} '{}' ".format(error_pos, e.message))