Bug 1729 fix
[osm/NBI.git] / osm_nbi / instance_topics.py
index 87b186e..f95ab21 100644 (file)
@@ -478,7 +478,6 @@ class NsrTopic(BaseTopic):
         ns_request["nsr_id"] = nsr_id
         if ns_request and ns_request.get("config-units"):
             nsr_descriptor["config-units"] = ns_request["config-units"]
-
         # Create vld
         if nsd.get("virtual-link-desc"):
             nsr_vld = deepcopy(nsd.get("virtual-link-desc", []))
@@ -709,10 +708,14 @@ class NsrTopic(BaseTopic):
             kdu_model = kdu_params.get("kdu_model") if kdu_params else None
             if kdu_params and kdu_params.get("k8s-namespace"):
                 kdu_k8s_namespace = kdu_params["k8s-namespace"]
+            kdu_deployment_name = ""
+            if kdu_params and kdu_params.get("kdu-deployment-name"):
+                kdu_deployment_name = kdu_params.get("kdu-deployment-name")
 
             kdur = {
                 "additionalParams": additional_params,
                 "k8s-namespace": kdu_k8s_namespace,
+                "kdu-deployment-name": kdu_deployment_name,
                 "kdu-name": kdu["name"],
                 # TODO      "name": ""     Name of the VDU in the VIM
                 "ip-address": None,  # mgmt-interface filled by LCM
@@ -933,9 +936,9 @@ class NsrTopic(BaseTopic):
             for index in range(0, count):
                 vdur = deepcopy(vdur)
                 for iface in vdur["interfaces"]:
-                    if iface.get("ip-address"):
+                    if iface.get("ip-address") and index != 0:
                         iface["ip-address"] = increment_ip_mac(iface["ip-address"])
-                    if iface.get("mac-address"):
+                    if iface.get("mac-address") and index != 0:
                         iface["mac-address"] = increment_ip_mac(iface["mac-address"])
 
                 vdur["_id"] = str(uuid4())
@@ -945,6 +948,41 @@ class NsrTopic(BaseTopic):
 
         return vnfr_descriptor
 
+    def vca_status_refresh(self, session, ns_instance_content, filter_q):
+        """
+        vcaStatus in ns_instance_content maybe stale, check if it is stale and create lcm op
+        to refresh vca status by sending message to LCM when it is stale. Ignore otherwise.
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
+        :param ns_instance_content:  ns instance content
+        :param filter_q: dict: query parameter containing vcaStatus-refresh as true or false
+        :return: None
+        """
+        time_now, time_delta = time(), time() - ns_instance_content["_admin"]["modified"]
+        force_refresh = isinstance(filter_q, dict) and filter_q.get('vcaStatusRefresh') == 'true'
+        threshold_reached = time_delta > 120
+        if force_refresh or threshold_reached:
+            operation, _id = "vca_status_refresh", ns_instance_content["_id"]
+            ns_instance_content["_admin"]["modified"] = time_now
+            self.db.set_one(self.topic, {"_id": _id}, ns_instance_content)
+            nslcmop_desc = NsLcmOpTopic._create_nslcmop(_id, operation, None)
+            self.format_on_new(nslcmop_desc, session["project_id"], make_public=session["public"])
+            nslcmop_desc["_admin"].pop("nsState")
+            self.msg.write("ns", operation, nslcmop_desc)
+        return
+
+    def show(self, session, _id, filter_q=None, api_req=False):
+        """
+        Get complete information on an ns instance.
+        :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
+        :param _id: string, ns instance id
+        :param filter_q: dict: query parameter containing vcaStatusRefresh as true or false
+        :param api_req: True if this call is serving an external API request. False if serving internal request.
+        :return: dictionary, raise exception if not found.
+        """
+        ns_instance_content = super().show(session, _id, api_req)
+        self.vca_status_refresh(session, ns_instance_content, filter_q)
+        return ns_instance_content
+
     def edit(self, session, _id, indata=None, kwargs=None, content=None):
         raise EngineException(
             "Method edit called directly", HTTPStatus.INTERNAL_SERVER_ERROR
@@ -1286,6 +1324,18 @@ class NsLcmOpTopic(BaseTopic):
             )
         vim_accounts.append(vim_account)
 
+    def _get_vim_account(self, vim_id: str, session):
+        try:
+            db_filter = self._get_project_filter(session)
+            db_filter["_id"] = vim_id
+            return self.db.get_one("vim_accounts", db_filter)
+        except Exception:
+            raise EngineException(
+                "Invalid vimAccountId='{}' not present for the project".format(
+                    vim_id
+                )
+            )
+
     def _check_valid_wim_account(self, wim_account, wim_accounts, session):
         if not isinstance(wim_account, str):
             return
@@ -1548,6 +1598,68 @@ class NsLcmOpTopic(BaseTopic):
             # TODO check that this forcing is not incompatible with other forcing
         return ifaces_forcing_vim_network
 
+    def _update_vnfrs_from_nsd(self, nsr):
+        try:
+            nsr_id = nsr["_id"]
+            nsd = nsr["nsd"]
+
+            step = "Getting vnf_profiles from nsd"
+            vnf_profiles = nsd.get("df", [{}])[0].get("vnf-profile", ())
+            vld_fixed_ip_connection_point_data = {}
+
+            step = "Getting ip-address info from vnf_profile if it exists"
+            for vnfp in vnf_profiles:
+                # Checking ip-address info from nsd.vnf_profile and storing
+                for vlc in vnfp.get("virtual-link-connectivity", ()):
+                    for cpd in vlc.get("constituent-cpd-id", ()):
+                        if cpd.get("ip-address"):
+                            step = "Storing ip-address info"
+                            vld_fixed_ip_connection_point_data.update({vlc.get("virtual-link-profile-id") + '.' + cpd.get("constituent-base-element-id"): {
+                                "vnfd-connection-point-ref": cpd.get(
+                                    "constituent-cpd-id"),
+                                    "ip-address": cpd.get(
+                                    "ip-address")}})
+
+            # Inserting ip address to vnfr
+            if len(vld_fixed_ip_connection_point_data) > 0:
+                step = "Getting vnfrs"
+                vnfrs = self.db.get_list("vnfrs", {"nsr-id-ref": nsr_id})
+                for item in vld_fixed_ip_connection_point_data.keys():
+                    step = "Filtering vnfrs"
+                    vnfr = next(filter(lambda vnfr: vnfr["member-vnf-index-ref"] == item.split('.')[1], vnfrs), None)
+                    if vnfr:
+                        vnfr_update = {}
+                        for vdur_index, vdur in enumerate(vnfr["vdur"]):
+                            for iface_index, iface in enumerate(vdur["interfaces"]):
+                                step = "Looking for matched interface"
+                                if (
+                                        iface.get("external-connection-point-ref")
+                                        == vld_fixed_ip_connection_point_data[item].get("vnfd-connection-point-ref") and
+                                        iface.get("ns-vld-id") == item.split('.')[0]
+
+                                ):
+                                    vnfr_update_text = "vdur.{}.interfaces.{}".format(
+                                        vdur_index, iface_index
+                                    )
+                                    step = "Storing info in order to update vnfr"
+                                    vnfr_update[
+                                        vnfr_update_text + ".ip-address"
+                                        ] = increment_ip_mac(
+                                        vld_fixed_ip_connection_point_data[item].get("ip-address"),
+                                        vdur.get("count-index", 0), )
+                                    vnfr_update[vnfr_update_text + ".fixed-ip"] = True
+
+                        step = "updating vnfr at database"
+                        self.db.set_one("vnfrs", {"_id": vnfr["_id"]}, vnfr_update)
+        except (
+                ValidationError,
+                EngineException,
+                DbException,
+                MsgException,
+                FsException,
+        ) as e:
+            raise type(e)("{} while '{}'".format(e, step), http_code=e.http_code)
+
     def _update_vnfrs(self, session, rollback, nsr, indata):
         # get vnfr
         nsr_id = nsr["_id"]
@@ -1560,15 +1672,14 @@ class NsLcmOpTopic(BaseTopic):
             # update vim-account-id
 
             vim_account = indata["vimAccountId"]
-            vca_id = indata.get("vcaId")
+            vca_id = self._get_vim_account(vim_account, session).get("vca")
             # check instantiate parameters
             for vnf_inst_params in get_iterable(indata.get("vnf")):
                 if vnf_inst_params["member-vnf-index"] != member_vnf_index:
                     continue
                 if vnf_inst_params.get("vimAccountId"):
                     vim_account = vnf_inst_params.get("vimAccountId")
-                if vnf_inst_params.get("vcaId"):
-                    vca_id = vnf_inst_params.get("vcaId")
+                    vca_id = self._get_vim_account(vim_account, session).get("vca")
 
                 # get vnf.vdu.interface instantiation params to update vnfr.vdur.interfaces ip, mac
                 for vdu_inst_param in get_iterable(vnf_inst_params.get("vdu")):
@@ -1868,6 +1979,7 @@ class NsLcmOpTopic(BaseTopic):
             self._check_ns_operation(session, nsr, operation, indata)
 
             if operation == "instantiate":
+                self._update_vnfrs_from_nsd(nsr)
                 self._update_vnfrs(session, rollback, nsr, indata)
 
             nslcmop_desc = self._create_nslcmop(nsInstanceId, operation, indata)