X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Finstance_topics.py;h=4a5293d178355a7fa0e6017e611031478d900d8e;hp=f9539dd7e0d512e3535be8e78101116ed14f3188;hb=HEAD;hpb=4cd875d2a38488b5e717258d548eeb8e557ec9a8 diff --git a/osm_nbi/instance_topics.py b/osm_nbi/instance_topics.py index f9539dd..695a8f8 100644 --- a/osm_nbi/instance_topics.py +++ b/osm_nbi/instance_topics.py @@ -31,6 +31,7 @@ from osm_nbi.validation import ( nsi_instantiate, ns_migrate, ns_verticalscale, + nslcmop_cancel, ) from osm_nbi.base_topic import ( BaseTopic, @@ -440,6 +441,23 @@ class NsrTopic(BaseTopic): return ns_k8s_namespace + def _add_shared_volumes_to_nsr( + self, vdu, vnfd, nsr_descriptor, member_vnf_index, revision=None + ): + svsd = [] + for vsd in vnfd.get("virtual-storage-desc", ()): + if vsd.get("vdu-storage-requirements"): + if ( + vsd.get("vdu-storage-requirements")[0].get("key") == "multiattach" + and vsd.get("vdu-storage-requirements")[0].get("value") == "True" + ): + # Avoid setting the volume name multiple times + if not match(f"shared-.*-{vnfd['id']}", vsd["id"]): + vsd["id"] = f"shared-{vsd['id']}-{vnfd['id']}" + svsd.append(vsd) + if svsd: + nsr_descriptor["shared-volumes"] = svsd + def _add_flavor_to_nsr( self, vdu, vnfd, nsr_descriptor, member_vnf_index, revision=None ): @@ -543,6 +561,8 @@ class NsrTopic(BaseTopic): "flavor": [], "image": [], "affinity-or-anti-affinity-group": [], + "shared-volumes": [], + "vnffgd": [], } if "revision" in nsd["_admin"]: nsr_descriptor["revision"] = nsd["_admin"]["revision"] @@ -580,6 +600,9 @@ class NsrTopic(BaseTopic): for vdu in vnfd.get("vdu", ()): member_vnf_index = vnf_profile.get("id") self._add_flavor_to_nsr(vdu, vnfd, nsr_descriptor, member_vnf_index) + self._add_shared_volumes_to_nsr( + vdu, vnfd, nsr_descriptor, member_vnf_index + ) sw_image_id = vdu.get("sw-image-desc") if sw_image_id: image_data = self._get_image_data_from_vnfd(vnfd, sw_image_id) @@ -619,6 +642,16 @@ class NsrTopic(BaseTopic): ) vld["name"] = vld["id"] nsr_descriptor["vld"] = nsr_vld + if nsd.get("vnffgd"): + vnffgd = nsd.get("vnffgd") + for vnffg in vnffgd: + info = {} + for k, v in vnffg.items(): + if k == "id": + info.update({k: v}) + if k == "nfpd": + info.update({k: v}) + nsr_descriptor["vnffgd"].append(info) return nsr_descriptor @@ -885,7 +918,7 @@ class NsrTopic(BaseTopic): # Name, mac-address and interface position is taken from VNFD # and included into VNFR. By this way RO can process this information # while creating the VDU. - iface_fields = ("name", "mac-address", "position") + iface_fields = ("name", "mac-address", "position", "ip-address") vdu_iface = { x: iface[x] for x in iface_fields if iface.get(x) is not None } @@ -955,7 +988,7 @@ class NsrTopic(BaseTopic): if ( cpd.get("constituent-cpd-id") == iface_ext_cp - ): + ) and vnf_profile.get("id") == vnf_index: vdu_iface["ns-vld-id"] = vlc.get( "virtual-link-profile-id" ) @@ -1021,6 +1054,21 @@ class NsrTopic(BaseTopic): if nsr_flavor_desc: vdur["ns-flavor-id"] = nsr_flavor_desc["id"] + # Adding Shared Volume information to vdur + if vdur.get("virtual-storages"): + nsr_sv = [] + for vsd in vdur["virtual-storages"]: + if vsd.get("vdu-storage-requirements"): + if ( + vsd["vdu-storage-requirements"][0].get("key") + == "multiattach" + and vsd["vdu-storage-requirements"][0].get("value") + == "True" + ): + nsr_sv.append(vsd["id"]) + if nsr_sv: + vdur["shared-volumes-id"] = nsr_sv + # Adding Affinity groups information to vdur try: vdu_profile_affinity_group = utils.find_in_list( @@ -1081,7 +1129,6 @@ class NsrTopic(BaseTopic): vdur["id"] = vdur["_id"] vdur["count-index"] = index vnfr_descriptor["vdur"].append(vdur) - return vnfr_descriptor def vca_status_refresh(self, session, ns_instance_content, filter_q): @@ -1168,6 +1215,7 @@ class NsLcmOpTopic(BaseTopic): "terminate": ns_terminate, "migrate": ns_migrate, "verticalscale": ns_verticalscale, + "cancel": nslcmop_cancel, } def __init__(self, db, fs, msg, auth): @@ -1535,8 +1583,8 @@ class NsLcmOpTopic(BaseTopic): ivld.get("id"): set() for ivld in get_iterable(vnfd.get("int-virtual-link-desc")) } - for vdu in get_iterable(vnfd.get("vdu")): - for cpd in get_iterable(vnfd.get("int-cpd")): + for vdu in vnfd.get("vdu", {}): + for cpd in vdu.get("int-cpd", {}): if cpd.get("int-virtual-link-desc"): vnfd_ivlds_cpds[cpd.get("int-virtual-link-desc")] = cpd.get("id") @@ -2279,6 +2327,9 @@ class NsLcmOpTopic(BaseTopic): vnf_index = vnfr["member-vnf-index-ref"] self.logger.info("nsr {}".format(nsr)) for vdu in vnfd["vdu"]: + self.nsrtopic._add_shared_volumes_to_nsr( + vdu, vnfd, nsr, vnf_index, latest_vnfd_revision + ) self.nsrtopic._add_flavor_to_nsr( vdu, vnfd, nsr, vnf_index, latest_vnfd_revision ) @@ -2295,6 +2346,7 @@ class NsLcmOpTopic(BaseTopic): self.nsrtopic._add_image_to_nsr(nsr, image_data) nsr_update["image"] = nsr["image"] nsr_update["flavor"] = nsr["flavor"] + nsr_update["shared-volumes"] = nsr["shared-volumes"] self.db.set_one("nsrs", {"_id": nsr["_id"]}, nsr_update) ns_k8s_namespace = self.nsrtopic._get_ns_k8s_namespace( nsd, ns_request, session @@ -2332,6 +2384,41 @@ class NsLcmOpTopic(BaseTopic): # except DbException as e: # raise EngineException("Cannot get ns_instance '{}': {}".format(e), HTTPStatus.NOT_FOUND) + def cancel(self, rollback, session, indata=None, kwargs=None, headers=None): + validate_input(indata, self.operation_schema["cancel"]) + # Override descriptor with query string kwargs + self._update_input_with_kwargs(indata, kwargs, yaml_format=True) + nsLcmOpOccId = indata["nsLcmOpOccId"] + cancelMode = indata["cancelMode"] + # get nslcmop from nsLcmOpOccId + _filter = BaseTopic._get_project_filter(session) + _filter["_id"] = nsLcmOpOccId + nslcmop = self.db.get_one("nslcmops", _filter) + # Fail is this is not an ongoing nslcmop + if nslcmop.get("operationState") not in [ + "STARTING", + "PROCESSING", + "ROLLING_BACK", + ]: + raise EngineException( + "Operation is not in STARTING, PROCESSING or ROLLING_BACK state", + http_code=HTTPStatus.CONFLICT, + ) + nsInstanceId = nslcmop["nsInstanceId"] + update_dict = { + "isCancelPending": True, + "cancelMode": cancelMode, + } + self.db.set_one( + "nslcmops", q_filter=_filter, update_dict=update_dict, fail_on_empty=False + ) + data = { + "_id": nsLcmOpOccId, + "nsInstanceId": nsInstanceId, + "cancelMode": cancelMode, + } + self.msg.write("nslcmops", "cancel", data) + def delete(self, session, _id, dry_run=False, not_send_msg=None): raise EngineException( "Method delete called directly", HTTPStatus.INTERNAL_SERVER_ERROR