X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_lcm%2Fns.py;h=19be20839734a9f7469876c1b5698c428bee3052;hb=refs%2Ftags%2Fv11.0.4;hp=17a892d1e9a8e7c09fb817d9308760538e78c43d;hpb=d8c29285954993b16205b7be406d8c3b96f05edd;p=osm%2FLCM.git diff --git a/osm_lcm/ns.py b/osm_lcm/ns.py index 17a892d..19be208 100644 --- a/osm_lcm/ns.py +++ b/osm_lcm/ns.py @@ -348,43 +348,49 @@ class NsLcm(LcmBase): self.logger.warn("Error updating NS state for ns={}: {}".format(nsr_id, e)) async def _on_update_k8s_db( - self, cluster_uuid, kdu_instance, filter=None, vca_id=None + self, cluster_uuid, kdu_instance, filter=None, vca_id=None, cluster_type="juju" ): """ Updating vca status in NSR record :param cluster_uuid: UUID of a k8s cluster :param kdu_instance: The unique name of the KDU instance :param filter: To get nsr_id + :cluster_type: The cluster type (juju, k8s) :return: none """ # self.logger.debug("_on_update_k8s_db(cluster_uuid={}, kdu_instance={}, filter={}" # .format(cluster_uuid, kdu_instance, filter)) + nsr_id = filter.get("_id") try: - nsr_id = filter.get("_id") - - # get vca status for NS - vca_status = await self.k8sclusterjuju.status_kdu( - cluster_uuid, - kdu_instance, - complete_status=True, + vca_status = await self.k8scluster_map[cluster_type].status_kdu( + cluster_uuid=cluster_uuid, + kdu_instance=kdu_instance, yaml_format=False, + complete_status=True, vca_id=vca_id, ) + # vcaStatus db_dict = dict() db_dict["vcaStatus"] = {nsr_id: vca_status} - await self.k8sclusterjuju.update_vca_status( - db_dict["vcaStatus"], - kdu_instance, - vca_id=vca_id, + if cluster_type in ("juju-bundle", "juju"): + # TODO -> this should be done in a more uniform way, I think in N2VC, in order to update the K8s VCA + # status in a similar way between Juju Bundles and Helm Charts on this side + await self.k8sclusterjuju.update_vca_status( + db_dict["vcaStatus"], + kdu_instance, + vca_id=vca_id, + ) + + self.logger.debug( + f"Obtained VCA status for cluster type '{cluster_type}': {vca_status}" ) # write to database self.update_db_2("nsrs", nsr_id, db_dict) - except (asyncio.CancelledError, asyncio.TimeoutError): raise except Exception as e: @@ -440,7 +446,8 @@ class NsLcm(LcmBase): def _get_vdu_additional_params(self, db_vnfr, vdu_id): vdur = next( - vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"] + (vdur for vdur in db_vnfr.get("vdur") if vdu_id == vdur["vdu-id-ref"]), + {} ) additional_params = vdur.get("additionalParams") return parse_yaml_strings(additional_params) @@ -517,6 +524,7 @@ class NsLcm(LcmBase): def scale_vnfr(self, db_vnfr, vdu_create=None, vdu_delete=None, mark_delete=False): db_vdu_push_list = [] + template_vdur = [] db_update = {"_admin.modified": time()} if vdu_create: for vdu_id, vdu_count in vdu_create.items(): @@ -529,12 +537,23 @@ class NsLcm(LcmBase): None, ) if not vdur: - raise LcmException( - "Error scaling OUT VNFR for {}. There is not any existing vnfr. Scaled to 0?".format( + # Read the template saved in the db: + self.logger.debug("No vdur in the database. Using the vdur-template to scale") + vdur_template = db_vnfr.get("vdur-template") + if not vdur_template: + raise LcmException( + "Error scaling OUT VNFR for {}. No vnfr or template exists".format( vdu_id + ) ) + vdur = vdur_template[0] + # Delete a template from the database after using it + self.db.set_one( + "vnfrs", + {"_id": db_vnfr["_id"]}, + None, + pull={"vdur-template": {"_id": vdur['_id']}} ) - for count in range(vdu_count): vdur_copy = deepcopy(vdur) vdur_copy["status"] = "BUILD" @@ -559,12 +578,17 @@ class NsLcm(LcmBase): ) else: iface.pop("mac-address", None) - iface.pop( - "mgmt_vnf", None - ) # only first vdu can be managment of vnf + if db_vnfr["vdur"]: + iface.pop( + "mgmt_vnf", None + ) # only first vdu can be managment of vnf db_vdu_push_list.append(vdur_copy) # self.logger.debug("scale out, adding vdu={}".format(vdur_copy)) if vdu_delete: + if len(db_vnfr["vdur"]) == 1: + # The scale will move to 0 instances + self.logger.debug("Scaling to 0 !, creating the template with the last vdur") + template_vdur = [db_vnfr["vdur"][0]] for vdu_id, vdu_count in vdu_delete.items(): if mark_delete: indexes_to_delete = [ @@ -592,7 +616,14 @@ class NsLcm(LcmBase): None, pull={"vdur": {"_id": vdu["_id"]}}, ) - db_push = {"vdur": db_vdu_push_list} if db_vdu_push_list else None + db_push = {} + if db_vdu_push_list: + db_push["vdur"] = db_vdu_push_list + if template_vdur: + db_push["vdur-template"] = template_vdur + if not db_push: + db_push = None + db_vnfr["vdur-template"] = template_vdur self.db.set_one("vnfrs", {"_id": db_vnfr["_id"]}, db_update, push_list=db_push) # modify passed dictionary db_vnfr db_vnfr_ = self.db.get_one("vnfrs", {"_id": db_vnfr["_id"]}) @@ -841,18 +872,55 @@ class NsLcm(LcmBase): get_iterable(vdur, "interfaces"), lambda iface: iface.get("ns-vld-id") == a_vld["name"], ) + + vld_params = find_in_list( + get_iterable(ns_params, "vld"), + lambda v_vld: v_vld["name"] in (a_vld["name"], a_vld["id"]), + ) if target_vld: + if vnf_params.get("vimAccountId") not in a_vld.get( "vim_info", {} ): + target_vim_network_list = [ + v for _, v in a_vld.get("vim_info").items() + ] + target_vim_network_name = next( + ( + item.get("vim_network_name", "") + for item in target_vim_network_list + ), + "", + ) + target["ns"]["vld"][a_index].get("vim_info").update( { "vim:{}".format(vnf_params["vimAccountId"]): { - "vim_network_name": "" + "vim_network_name": target_vim_network_name, } } ) + if vld_params: + for param in ("vim-network-name", "vim-network-id"): + if vld_params.get(param) and isinstance( + vld_params[param], dict + ): + for vim, vim_net in vld_params[ + param + ].items(): + other_target_vim = "vim:" + vim + populate_dict( + target["ns"]["vld"][a_index].get( + "vim_info" + ), + ( + other_target_vim, + param.replace("-", "_"), + ), + vim_net, + ) + nslcmop_id = db_nslcmop["_id"] target = { "name": db_nsr["name"], @@ -867,6 +935,10 @@ class NsLcm(LcmBase): image["vim_info"] = {} for flavor in target["flavor"]: flavor["vim_info"] = {} + if db_nsr.get("affinity-or-anti-affinity-group"): + target["affinity-or-anti-affinity-group"] = deepcopy(db_nsr["affinity-or-anti-affinity-group"]) + for affinity_or_anti_affinity_group in target["affinity-or-anti-affinity-group"]: + affinity_or_anti_affinity_group["vim_info"] = {} if db_nslcmop.get("lcmOperationType") != "instantiate": # get parameters of instantiation: @@ -1159,6 +1231,13 @@ class NsLcm(LcmBase): if target_vim not in ns_image["vim_info"]: ns_image["vim_info"][target_vim] = {} + # Affinity groups + if vdur.get("affinity-or-anti-affinity-group-id"): + for ags_id in vdur["affinity-or-anti-affinity-group-id"]: + ns_ags = target["affinity-or-anti-affinity-group"][int(ags_id)] + if target_vim not in ns_ags["vim_info"]: + ns_ags["vim_info"][target_vim] = {} + vdur["vim_info"] = {target_vim: {}} # instantiation parameters # if vnf_params: @@ -1933,6 +2012,9 @@ class NsLcm(LcmBase): step = "Waiting to VM being up and getting IP address" self.logger.debug(logging_text + step) + # default rw_mgmt_ip to None, avoiding the non definition of the variable + rw_mgmt_ip = None + # n2vc_redesign STEP 5.1 # wait for RO (ip-address) Insert pub_key into VM if vnfr_id: @@ -1940,7 +2022,13 @@ class NsLcm(LcmBase): rw_mgmt_ip = await self.wait_kdu_up( logging_text, nsr_id, vnfr_id, kdu_name ) - else: + + # This verification is needed in order to avoid trying to add a public key + # to a VM, when the VNF is a KNF (in the edge case where the user creates a VCA + # for a KNF and not for its KDUs, the previous verification gives False, and the code + # jumps to this block, meaning that there is the need to verify if the VNF is actually a VNF + # or it is a KNF) + elif db_vnfr.get('vdur'): rw_mgmt_ip = await self.wait_vm_up_insert_key_ro( logging_text, nsr_id, @@ -1950,8 +2038,6 @@ class NsLcm(LcmBase): user=user, pub_key=pub_key, ) - else: - rw_mgmt_ip = None # This is for a NS configuration self.logger.debug(logging_text + " VM_ip_address={}".format(rw_mgmt_ip)) @@ -2042,7 +2128,7 @@ class NsLcm(LcmBase): }, job, upsert=True, - fail_on_empty=False + fail_on_empty=False, ) step = "instantiated at VCA" @@ -2344,7 +2430,9 @@ class NsLcm(LcmBase): kdur_list = [] for kdur in vnfr["kdur"]: if kdur.get("additionalParams"): - kdur["additionalParams"] = json.loads(kdur["additionalParams"]) + kdur["additionalParams"] = json.loads( + kdur["additionalParams"] + ) kdur_list.append(kdur) vnfr["kdur"] = kdur_list @@ -2542,8 +2630,8 @@ class NsLcm(LcmBase): ) deploy_params_kdu = {"OSM": get_osm_params(db_vnfr)} if kdur.get("additionalParams"): - deploy_params_kdu = parse_yaml_strings( - kdur["additionalParams"] + deploy_params_kdu.update( + parse_yaml_strings(kdur["additionalParams"].copy()) ) self._deploy_n2vc( @@ -3114,9 +3202,45 @@ class NsLcm(LcmBase): kdu_model=k8s_instance_info["kdu-model"], kdu_name=k8s_instance_info["kdu-name"], ) + + # Update the nsrs table with the kdu-instance value self.update_db_2( - "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance} + item="nsrs", + _id=nsr_id, + _desc={nsr_db_path + ".kdu-instance": kdu_instance}, ) + + # Update the nsrs table with the actual namespace being used, if the k8scluster-type is `juju` or + # `juju-bundle`. This verification is needed because there is not a standard/homogeneous namespace + # between the Helm Charts and Juju Bundles-based KNFs. If we found a way of having an homogeneous + # namespace, this first verification could be removed, and the next step would be done for any kind + # of KNF. + # TODO -> find a way to have an homogeneous namespace between the Helm Charts and Juju Bundles-based + # KNFs (Bug 2027: https://osm.etsi.org/bugzilla/show_bug.cgi?id=2027) + if k8sclustertype in ("juju", "juju-bundle"): + # First, verify if the current namespace is present in the `_admin.projects_read` (if not, it means + # that the user passed a namespace which he wants its KDU to be deployed in) + if ( + self.db.count( + table="nsrs", + q_filter={ + "_id": nsr_id, + "_admin.projects_write": k8s_instance_info["namespace"], + "_admin.projects_read": k8s_instance_info["namespace"], + }, + ) + > 0 + ): + self.logger.debug( + f"Updating namespace/model for Juju Bundle from {k8s_instance_info['namespace']} to {kdu_instance}" + ) + self.update_db_2( + item="nsrs", + _id=nsr_id, + _desc={f"{nsr_db_path}.namespace": kdu_instance}, + ) + k8s_instance_info["namespace"] = kdu_instance + await self.k8scluster_map[k8sclustertype].install( cluster_uuid=k8s_instance_info["k8scluster-uuid"], kdu_model=k8s_instance_info["kdu-model"], @@ -3129,9 +3253,6 @@ class NsLcm(LcmBase): kdu_instance=kdu_instance, vca_id=vca_id, ) - self.update_db_2( - "nsrs", nsr_id, {nsr_db_path + ".kdu-instance": kdu_instance} - ) # Obtain services to obtain management service ip services = await self.k8scluster_map[k8sclustertype].get_services( @@ -3488,7 +3609,7 @@ class NsLcm(LcmBase): vnfd_with_id, k8s_instance_info, k8params=desc_params, - timeout=600, + timeout=1800, vca_id=vca_id, ) ) @@ -4825,10 +4946,18 @@ class NsLcm(LcmBase): db_nsr = self.db.get_one("nsrs", {"_id": nsr_id}) vca_id = self.get_vca_id({}, db_nsr) if db_nsr["_admin"]["deployed"]["K8s"]: - for k8s_index, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]): - cluster_uuid, kdu_instance = k8s["k8scluster-uuid"], k8s["kdu-instance"] + for _, k8s in enumerate(db_nsr["_admin"]["deployed"]["K8s"]): + cluster_uuid, kdu_instance, cluster_type = ( + k8s["k8scluster-uuid"], + k8s["kdu-instance"], + k8s["k8scluster-type"], + ) await self._on_update_k8s_db( - cluster_uuid, kdu_instance, filter={"_id": nsr_id}, vca_id=vca_id + cluster_uuid=cluster_uuid, + kdu_instance=kdu_instance, + filter={"_id": nsr_id}, + vca_id=vca_id, + cluster_type=cluster_type, ) else: for vca_index, _ in enumerate(db_nsr["_admin"]["deployed"]["VCA"]): @@ -4895,7 +5024,9 @@ class NsLcm(LcmBase): kdur_list = [] for kdur in db_vnfr["kdur"]: if kdur.get("additionalParams"): - kdur["additionalParams"] = json.loads(kdur["additionalParams"]) + kdur["additionalParams"] = json.loads( + kdur["additionalParams"] + ) kdur_list.append(kdur) db_vnfr["kdur"] = kdur_list step = "Getting vnfd from database" @@ -6400,13 +6531,7 @@ class NsLcm(LcmBase): ) async def extract_prometheus_scrape_jobs( - self, - ee_id, - artifact_path, - ee_config_descriptor, - vnfr_id, - nsr_id, - target_ip + self, ee_id, artifact_path, ee_config_descriptor, vnfr_id, nsr_id, target_ip ): # look if exist a file called 'prometheus*.j2' and artifact_content = self.fs.dir_ls(artifact_path)