Fix Bug 1911 Root disk cannot be a Persistent Volume
[osm/RO.git] / NG-RO / osm_ng_ro / ns.py
index 2db33e4..3a7929c 100644 (file)
 # limitations under the License.
 ##
 
-# import yaml
+from http import HTTPStatus
 import logging
+from random import choice as random_choice
+from threading import Lock
+from time import time
 from traceback import format_exc as traceback_format_exc
-from osm_ng_ro.ns_thread import NsWorker, NsWorkerException, deep_get
-from osm_ng_ro.validation import validate_input, deploy_schema
+from uuid import uuid4
+
+from cryptography.hazmat.backends import default_backend as crypto_default_backend
+from cryptography.hazmat.primitives import serialization as crypto_serialization
+from cryptography.hazmat.primitives.asymmetric import rsa
+from jinja2 import (
+    Environment,
+    StrictUndefined,
+    TemplateError,
+    TemplateNotFound,
+    UndefinedError,
+)
 from osm_common import (
-    dbmongo,
     dbmemory,
+    dbmongo,
     fslocal,
     fsmongo,
-    msglocal,
     msgkafka,
+    msglocal,
     version as common_version,
 )
 from osm_common.dbbase import DbException
 from osm_common.fsbase import FsException
 from osm_common.msgbase import MsgException
-from http import HTTPStatus
-from uuid import uuid4
-from threading import Lock
-from random import choice as random_choice
-from time import time
-from jinja2 import (
-    Environment,
-    TemplateError,
-    TemplateNotFound,
-    StrictUndefined,
-    UndefinedError,
-)
-from cryptography.hazmat.primitives import serialization as crypto_serialization
-from cryptography.hazmat.primitives.asymmetric import rsa
-from cryptography.hazmat.backends import default_backend as crypto_default_backend
+from osm_ng_ro.ns_thread import deep_get, NsWorker, NsWorkerException
+from osm_ng_ro.validation import deploy_schema, validate_input
 
 __author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
 min_common_version = "0.1.16"
@@ -539,6 +539,8 @@ class Ns(object):
 
                     return quota
 
+                nonlocal indata
+
                 flavor_data = {
                     "disk": int(target_flavor["storage-gb"]),
                     "ram": int(target_flavor["memory-mb"]),
@@ -547,6 +549,26 @@ class Ns(object):
                 numa = {}
                 extended = {}
 
+                target_vdur = None
+                for vnf in indata.get("vnf", []):
+                    for vdur in vnf.get("vdur", []):
+                        if vdur.get("ns-flavor-id") == target_flavor["id"]:
+                            target_vdur = vdur
+
+                for storage in target_vdur.get("virtual-storages", []):
+                    if (
+                        storage.get("type-of-storage")
+                        == "etsi-nfv-descriptors:ephemeral-storage"
+                    ):
+                        flavor_data["ephemeral"] = int(
+                            storage.get("size-of-storage", 0)
+                        )
+                    elif (
+                        storage.get("type-of-storage")
+                        == "etsi-nfv-descriptors:swap-storage"
+                    ):
+                        flavor_data["swap"] = int(storage.get("size-of-storage", 0))
+
                 if target_flavor.get("guest-epa"):
                     extended = {}
                     epa_vcpu_set = False
@@ -671,6 +693,28 @@ class Ns(object):
 
                 return extra_dict
 
+            def _process_affinity_group_params(
+                target_affinity_group, vim_info, target_record_id
+            ):
+                extra_dict = {}
+
+                affinity_group_data = {
+                    "name": target_affinity_group["name"],
+                    "type": target_affinity_group["type"],
+                    "scope": target_affinity_group["scope"],
+                }
+
+                if target_affinity_group.get("vim-affinity-group-id"):
+                    affinity_group_data[
+                        "vim-affinity-group-id"
+                    ] = target_affinity_group["vim-affinity-group-id"]
+
+                extra_dict["params"] = {
+                    "affinity_group_data": affinity_group_data,
+                }
+
+                return extra_dict
+
             def _ip_profile_2_ro(ip_profile):
                 if not ip_profile:
                     return None
@@ -687,9 +731,7 @@ class Ns(object):
                     "dhcp_start_address": ip_profile.get("dhcp-params", {}).get(
                         "start-address", None
                     ),
-                    "dhcp_count": ip_profile.get("dhcp-params", {}).get(
-                        "count", None
-                    ),
+                    "dhcp_count": ip_profile.get("dhcp-params", {}).get("count", None),
                 }
 
                 if ip_profile.get("dns-server"):
@@ -785,6 +827,17 @@ class Ns(object):
                         continue  # interface not connected to any vld
 
                     extra_dict["depends_on"].append(net_text)
+
+                    if "port-security-enabled" in interface:
+                        interface["port_security"] = interface.pop(
+                            "port-security-enabled"
+                        )
+
+                    if "port-security-disable-strategy" in interface:
+                        interface["port_security_disable_strategy"] = interface.pop(
+                            "port-security-disable-strategy"
+                        )
+
                     net_item = {
                         x: v
                         for x, v in interface.items()
@@ -868,6 +921,57 @@ class Ns(object):
                 if ssh_keys:
                     cloud_config["key-pairs"] = ssh_keys
 
+                persistent_root_disk = {}
+                disk_list = []
+                vnfd_id = vnfr["vnfd-id"]
+                vnfd = self.db.get_one("vnfds", {"_id": vnfd_id})
+                for vdu in vnfd.get("vdu", ()):
+                    if vdu["name"] == target_vdu["vdu-name"]:
+                        for vsd in vnfd.get("virtual-storage-desc", ()):
+                            if (
+                                vsd.get("id")
+                                == vdu.get("virtual-storage-desc", [[]])[0]
+                            ):
+                                root_disk = vsd
+                                if root_disk.get(
+                                    "type-of-storage"
+                                ) == "persistent-storage:persistent-storage" and root_disk.get(
+                                    "size-of-storage"
+                                ):
+                                    persistent_root_disk[vsd["id"]] = {
+                                        "image_id": vdu.get("sw-image-desc"),
+                                        "size": root_disk["size-of-storage"],
+                                    }
+                                    disk_list.append(persistent_root_disk[vsd["id"]])
+
+                if target_vdu.get("virtual-storages"):
+                    for disk in target_vdu["virtual-storages"]:
+                        if (
+                            disk.get("type-of-storage")
+                            == "persistent-storage:persistent-storage"
+                            and disk["id"] not in persistent_root_disk.keys()
+                        ):
+                            disk_list.append({"size": disk["size-of-storage"]})
+
+                affinity_group_list = []
+
+                if target_vdu.get("affinity-or-anti-affinity-group-id"):
+                    affinity_group = {}
+                    for affinity_group_id in target_vdu[
+                        "affinity-or-anti-affinity-group-id"
+                    ]:
+                        affinity_group_text = (
+                            ns_preffix
+                            + ":affinity-or-anti-affinity-group."
+                            + affinity_group_id
+                        )
+
+                        extra_dict["depends_on"].append(affinity_group_text)
+                        affinity_group["affinity_group_id"] = (
+                            "TASK-" + affinity_group_text
+                        )
+                        affinity_group_list.append(affinity_group)
+
                 extra_dict["params"] = {
                     "name": "{}-{}-{}-{}".format(
                         indata["name"][:16],
@@ -879,9 +983,10 @@ class Ns(object):
                     "start": True,
                     "image_id": "TASK-" + image_text,
                     "flavor_id": "TASK-" + flavor_text,
+                    "affinity_group_list": affinity_group_list,
                     "net_list": net_list,
                     "cloud_config": cloud_config or None,
-                    "disk_list": None,  # TODO
+                    "disk_list": disk_list,
                     "availability_zone_index": None,  # TODO
                     "availability_zone_list": None,  # TODO
                 }
@@ -1116,6 +1221,20 @@ class Ns(object):
                         process_params=_process_flavor_params,
                     )
 
+                    step = "process NS Affinity Groups"
+                    _process_items(
+                        target_list=indata.get("affinity-or-anti-affinity-group") or [],
+                        existing_list=db_nsr.get("affinity-or-anti-affinity-group")
+                        or [],
+                        db_record="nsrs:{}:affinity-or-anti-affinity-group".format(
+                            nsr_id
+                        ),
+                        db_update=db_nsr_update,
+                        db_path="affinity-or-anti-affinity-group",
+                        item="affinity-or-anti-affinity-group",
+                        process_params=_process_affinity_group_params,
+                    )
+
                     # VNF.vld
                     for vnfr_id, vnfr in db_vnfrs.items():
                         # vnfr_id need to be set as global variable for among others nested method _process_vdu_params