X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fdescriptor_topics.py;h=f388ad186b03b481c4b161dae9c7023ff1fccbe4;hp=d01dc1396a772512023e4b32df6f5c35bf6ff22e;hb=45bd94c2a096f53a5692f438aa5148c3d42631fa;hpb=32bab47c7fde8ae22795306723f3441ec544fa2b diff --git a/osm_nbi/descriptor_topics.py b/osm_nbi/descriptor_topics.py index d01dc13..f388ad1 100644 --- a/osm_nbi/descriptor_topics.py +++ b/osm_nbi/descriptor_topics.py @@ -20,6 +20,7 @@ import json from hashlib import md5 from osm_common.dbbase import DbException, deep_update_rfc7396 from http import HTTPStatus +from time import time from osm_nbi.validation import ValidationError, pdu_new_schema, pdu_edit_schema from osm_nbi.base_topic import BaseTopic, EngineException, get_iterable from osm_im.vnfd import vnfd as vnfd_im @@ -38,6 +39,27 @@ class DescriptorTopic(BaseTopic): def check_conflict_on_edit(self, session, final_content, edit_content, _id): super().check_conflict_on_edit(session, final_content, edit_content, _id) + + def _check_unique_id_name(descriptor, position=""): + for desc_key, desc_item in descriptor.items(): + if isinstance(desc_item, list) and desc_item: + used_ids = [] + desc_item_id = None + for index, list_item in enumerate(desc_item): + if isinstance(list_item, dict): + _check_unique_id_name(list_item, "{}.{}[{}]" + .format(position, desc_key, index)) + # Base case + if index == 0 and (list_item.get("id") or list_item.get("name")): + desc_item_id = "id" if list_item.get("id") else "name" + if desc_item_id and list_item.get(desc_item_id): + if list_item[desc_item_id] in used_ids: + position = "{}.{}[{}]".format(position, desc_key, index) + raise EngineException("Error: identifier {} '{}' is not unique and repeats at '{}'" + .format(desc_item_id, list_item[desc_item_id], + position), HTTPStatus.UNPROCESSABLE_ENTITY) + used_ids.append(list_item[desc_item_id]) + _check_unique_id_name(final_content) # 1. validate again with pyangbind # 1.1. remove internal keys internal_keys = {} @@ -139,6 +161,7 @@ class DescriptorTopic(BaseTopic): self.format_on_new(content, session["project_id"], make_public=session["public"]) _id = self.db.create(self.topic, content) rollback.append({"topic": self.topic, "_id": _id}) + self._send_msg("created", {"_id": _id}) return _id, None except ValidationError as e: raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY) @@ -264,7 +287,7 @@ class DescriptorTopic(BaseTopic): indata = json.load(content) else: error_text = "Invalid yaml format " - indata = yaml.load(content) + indata = yaml.load(content, Loader=yaml.SafeLoader) current_desc["_admin"]["storage"] = storage current_desc["_admin"]["onboardingState"] = "ONBOARDED" @@ -280,11 +303,12 @@ class DescriptorTopic(BaseTopic): deep_update_rfc7396(current_desc, indata) self.check_conflict_on_edit(session, current_desc, indata, _id=_id) + current_desc["_admin"]["modified"] = time() self.db.replace(self.topic, _id, current_desc) self.fs.dir_rename(temp_folder, _id) indata["_id"] = _id - self._send_msg("created", indata) + self._send_msg("edited", indata) # TODO if descriptor has changed because kwargs update content and remove cached zip # TODO if zip is not present creates one @@ -703,6 +727,19 @@ class NsdTopic(DescriptorTopic): "does not match any constituent-vnfd:member-vnf-index" .format(vld["id"], vnfd_cp["member-vnf-index-ref"]), http_code=HTTPStatus.UNPROCESSABLE_ENTITY) + # Check VNFFGD + for fgd in get_iterable(indata.get("vnffgd")): + for cls in get_iterable(fgd.get("classifier")): + rspref = cls.get("rsp-id-ref") + for rsp in get_iterable(fgd.get("rsp")): + rspid = rsp.get("id") + if rspid and rspref and rspid == rspref: + break + else: + raise EngineException( + "Error at vnffgd[id='{}']:classifier[id='{}']:rsp-id-ref '{}' does not match any rsp:id" + .format(fgd["id"], cls["id"], rspref), + http_code=HTTPStatus.UNPROCESSABLE_ENTITY) return indata def _validate_input_edit(self, indata, force=False): @@ -739,11 +776,6 @@ class NsdTopic(DescriptorTopic): for referenced_vnfd_cp in get_iterable(vld.get("vnfd-connection-point-ref")): # look if this vnfd contains this connection point vnfd = member_vnfd_index.get(referenced_vnfd_cp["member-vnf-index-ref"]) - if not vnfd: - raise EngineException("Error at vld[id='{}']:vnfd-connection-point-ref[member-vnf-index-ref='{}'] " - "does not match any constituent-vnfd:member-vnf-index" - .format(vld["id"], referenced_vnfd_cp["member-vnf-index-ref"]), - http_code=HTTPStatus.UNPROCESSABLE_ENTITY) for vnfd_cp in get_iterable(vnfd.get("connection-point")): if referenced_vnfd_cp.get("vnfd-connection-point-ref") == vnfd_cp["name"]: break