Feature 10908: NBI Revisions
[osm/NBI.git] / osm_nbi / instance_topics.py
index 22580d1..b4ce270 100644 (file)
@@ -348,6 +348,9 @@ class NsrTopic(BaseTopic):
                 )
                 if vnfd_id not in needed_vnfds:
                     vnfd = self._get_vnfd_from_db(vnfd_id, session)
+                    if "revision" in vnfd["_admin"]:
+                        vnfd["revision"] = vnfd["_admin"]["revision"]
+                    vnfd.pop("_admin")
                     needed_vnfds[vnfd_id] = vnfd
                     nsr_descriptor["vnfd-id"].append(vnfd["_id"])
                 else:
@@ -397,7 +400,6 @@ class NsrTopic(BaseTopic):
         _filter = self._get_project_filter(session)
         _filter["id"] = vnfd_id
         vnfd = self.db.get_one("vnfds", _filter, fail_on_empty=True, fail_on_more=True)
-        vnfd.pop("_admin")
         return vnfd
 
     def _add_nsr_to_db(self, nsr_descriptor, rollback, session):
@@ -477,6 +479,7 @@ class NsrTopic(BaseTopic):
             "ssh-authorized-key": ns_request.get("ssh_keys"),  # TODO remove
             "flavor": [],
             "image": [],
+            "affinity-or-anti-affinity-group": [],
         }
         ns_request["nsr_id"] = nsr_id
         if ns_request and ns_request.get("config-units"):
@@ -506,6 +509,7 @@ class NsrTopic(BaseTopic):
                         )
 
                 vnfd = self._get_vnfd_from_db(vnf_profile.get("vnfd-id"), session)
+                vnfd.pop("_admin")
 
                 for vdu in vnfd.get("vdu", ()):
                     flavor_data = {}
@@ -591,6 +595,16 @@ class NsrTopic(BaseTopic):
                         image_data = self._get_image_data_from_vnfd(vnfd, alt_image)
                         self._add_image_to_nsr(nsr_descriptor, image_data)
 
+                # Add Affinity or Anti-affinity group information to NSR
+                vdu_profiles = vnfd.get("df", [[]])[0].get("vdu-profile", ())
+                ag_prefix_name = "{}-{}".format(nsr_descriptor["name"][:16], vnf_profile.get("id")[:16])
+
+                for vdu_profile in vdu_profiles:
+                    ag_data = {}
+                    for ag in vdu_profile.get("affinity-or-anti-affinity-group", ()):
+                        ag_data = self._get_affinity_or_anti_affinity_group_data_from_vnfd(vnfd, ag["id"])
+                        self._add_affinity_or_anti_affinity_group_to_nsr(nsr_descriptor, ag_data, ag_prefix_name)
+
             for vld in nsr_vld:
                 vld["vnfd-connection-point-ref"] = all_vld_connection_point_data.get(
                     vld.get("id"), []
@@ -600,6 +614,39 @@ class NsrTopic(BaseTopic):
 
         return nsr_descriptor
 
+    def _get_affinity_or_anti_affinity_group_data_from_vnfd(self, vnfd, ag_id):
+        """
+        Gets affinity-or-anti-affinity-group info from df and returns the desired affinity group
+        """
+        affinity_or_anti_affinity_group = utils.find_in_list(
+            vnfd.get("df", [[]])[0].get("affinity-or-anti-affinity-group", ()), lambda ag: ag["id"] == ag_id
+        )
+        ag_data = {}
+        if affinity_or_anti_affinity_group and affinity_or_anti_affinity_group.get("id"):
+            ag_data["ag-id"] = affinity_or_anti_affinity_group["id"]
+        if affinity_or_anti_affinity_group and affinity_or_anti_affinity_group.get("type"):
+            ag_data["type"] = affinity_or_anti_affinity_group["type"]
+        if affinity_or_anti_affinity_group and affinity_or_anti_affinity_group.get("scope"):
+            ag_data["scope"] = affinity_or_anti_affinity_group["scope"]
+        return ag_data
+
+    def _add_affinity_or_anti_affinity_group_to_nsr(self, nsr_descriptor, ag_data, ag_prefix_name):
+        """
+        Adds affinity-or-anti-affinity-group to nsr checking first it is not already added
+        """
+        ag = next(
+            (
+                f
+                for f in nsr_descriptor["affinity-or-anti-affinity-group"]
+                if all(f.get(k) == ag_data[k] for k in ag_data)
+            ),
+            None,
+        )
+        if not ag:
+            ag_data["id"] = str(len(nsr_descriptor["affinity-or-anti-affinity-group"]))
+            ag_data["name"] = "{}-{}-{}".format(ag_prefix_name, ag_data["ag-id"][:32], ag_data.get("id") or 0)
+            nsr_descriptor["affinity-or-anti-affinity-group"].append(ag_data)
+
     def _get_image_data_from_vnfd(self, vnfd, sw_image_id):
         sw_image_desc = utils.find_in_list(
             vnfd.get("sw-image-desc", ()), lambda sw: sw["id"] == sw_image_id
@@ -662,6 +709,13 @@ class NsrTopic(BaseTopic):
             "connection-point": [],
             "ip-address": None,  # mgmt-interface filled by LCM
         }
+
+        # Revision backwards compatility.  Only specify the revision in the record if
+        # the original VNFD has a revision.
+        if "revision" in vnfd:
+            vnfr_descriptor["revision"] = vnfd["revision"]
+
+
         vnf_k8s_namespace = ns_k8s_namespace
         if vnf_params:
             if vnf_params.get("k8s-namespace"):
@@ -941,6 +995,31 @@ class NsrTopic(BaseTopic):
             if nsr_flavor_desc:
                 vdur["ns-flavor-id"] = nsr_flavor_desc["id"]
 
+            # Adding Affinity groups information to vdur
+            try:
+                ags_vdu_profile = utils.find_in_list(
+                    vnfd.get("df")[0]["vdu-profile"],
+                    lambda a_vdu: a_vdu["id"] == vdu["id"],
+                )
+            except Exception:
+                ags_vdu_profile = None
+
+            if ags_vdu_profile:
+                ags_ids = []
+                for ag in ags_vdu_profile.get("affinity-or-anti-affinity-group", ()):
+                    vdu_ag = utils.find_in_list(
+                        ags_vdu_profile.get("affinity-or-anti-affinity-group", ()),
+                        lambda ag_fp: ag_fp["id"] == ag["id"],
+                    )
+                    nsr_ags_data = utils.find_in_list(
+                        nsr_descriptor["affinity-or-anti-affinity-group"],
+                        lambda nsr_ag: (
+                            nsr_ag.get("ag-id") == vdu_ag.get("id")
+                        ),
+                    )
+                    ags_ids.append(nsr_ags_data["id"])
+                vdur["affinity-or-anti-affinity-group-id"] = ags_ids
+
             if vdu_instantiation_level:
                 count = vdu_instantiation_level.get("number-of-instances")
             else:
@@ -1213,7 +1292,14 @@ class NsLcmOpTopic(BaseTopic):
                 "Invalid parameter member_vnf_index='{}' is not one of the "
                 "nsd:constituent-vnfd".format(member_vnf_index)
             )
-        vnfd = self.db.get_one("vnfds", {"_id": vnfr["vnfd-id"]}, fail_on_empty=False)
+
+        ## Backwards compatibility: if there is no revision, get it from the one and only VNFD entry
+        if "revision" in vnfr:
+            vnfd_revision = vnfr["vnfd-id"] + ":" + str(vnfr["revision"])
+            vnfd = self.db.get_one("vnfds_revisions", {"_id": vnfd_revision}, fail_on_empty=False)
+        else:
+            vnfd = self.db.get_one("vnfds", {"_id": vnfr["vnfd-id"]}, fail_on_empty=False)
+
         if not vnfd:
             raise EngineException(
                 "vnfd id={} has been deleted!. Operation cannot be performed".format(