:return: _id, None: identity of the inserted data; and None as there is not any operation
"""
- try:
- # Check Quota
- self.check_quota(session)
+ # No needed to capture exceptions
+ # Check Quota
+ self.check_quota(session)
- # _remove_envelop
- if indata:
- if "userDefinedData" in indata:
- indata = indata['userDefinedData']
+ # _remove_envelop
+ if indata:
+ if "userDefinedData" in indata:
+ indata = indata['userDefinedData']
- # Override descriptor with query string kwargs
- self._update_input_with_kwargs(indata, kwargs)
- # uncomment when this method is implemented.
- # Avoid override in this case as the target is userDefinedData, but not vnfd,nsd descriptors
- # indata = DescriptorTopic._validate_input_new(self, indata, project_id=session["force"])
-
- content = {"_admin": {"userDefinedData": indata}}
- 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)
+ # Override descriptor with query string kwargs
+ self._update_input_with_kwargs(indata, kwargs)
+ # uncomment when this method is implemented.
+ # Avoid override in this case as the target is userDefinedData, but not vnfd,nsd descriptors
+ # indata = DescriptorTopic._validate_input_new(self, indata, project_id=session["force"])
+
+ content = {"_admin": {"userDefinedData": indata}}
+ 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
def upload_content(self, session, _id, indata, kwargs, headers):
"""
raise EngineException("Error in pyangbind validation: {}".format(str(e)),
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
+ def _validate_input_edit(self, indata, content, force=False):
+ # not needed to validate with pyangbind becuase it will be validated at check_conflict_on_edit
+ if "_id" in indata:
+ indata.pop("_id")
+ if "_admin" not in indata:
+ indata["_admin"] = {}
+
+ if "operationalState" in indata:
+ if indata["operationalState"] in ("ENABLED", "DISABLED"):
+ indata["_admin"]["operationalState"] = indata.pop("operationalState")
+ else:
+ raise EngineException("State '{}' is not a valid operational state"
+ .format(indata["operationalState"]),
+ http_code=HTTPStatus.BAD_REQUEST)
+
+ # In the case of user defined data, we need to put the data in the root of the object
+ # to preserve current expected behaviour
+ if "userDefinedData" in indata:
+ data = indata.pop("userDefinedData")
+ if type(data) == dict:
+ indata["_admin"]["userDefinedData"] = data
+ else:
+ raise EngineException("userDefinedData should be an object, but is '{}' instead"
+ .format(type(data)),
+ http_code=HTTPStatus.BAD_REQUEST)
+
+ if ("operationalState" in indata["_admin"] and
+ content["_admin"]["operationalState"] == indata["_admin"]["operationalState"]):
+ raise EngineException("operationalState already {}".format(content["_admin"]["operationalState"]),
+ http_code=HTTPStatus.CONFLICT)
+
+ return indata
+
class VnfdTopic(DescriptorTopic):
topic = "vnfds"
http_code=HTTPStatus.CONFLICT)
def _validate_input_new(self, indata, storage_params, force=False):
+ indata.pop("onboardingState", None)
+ indata.pop("operationalState", None)
+ indata.pop("usageState", None)
+
+ indata.pop("links", None)
+
indata = self.pyangbind_validation("vnfds", indata, force)
# Cross references validation in the descriptor
if indata.get("vdu"):
vld_names = [] # For detection of duplicated VLD names
for ivld in get_iterable(indata.get("internal-vld")):
# BEGIN Detection of duplicated VLD names
- ivld_name = ivld["name"]
- if ivld_name in vld_names:
- raise EngineException("Duplicated VLD name '{}' in vnfd[id={}]:internal-vld[id={}]"
- .format(ivld["name"], indata["id"], ivld["id"]),
- http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
- else:
- vld_names.append(ivld_name)
+ ivld_name = ivld.get("name")
+ if ivld_name:
+ if ivld_name in vld_names:
+ raise EngineException("Duplicated VLD name '{}' in vnfd[id={}]:internal-vld[id={}]"
+ .format(ivld["name"], indata["id"], ivld["id"]),
+ http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
+ else:
+ vld_names.append(ivld_name)
# END Detection of duplicated VLD names
for icp in get_iterable(ivld.get("internal-connection-point")):
icp_mark = False
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
return indata
- def _validate_input_edit(self, indata, force=False):
- # not needed to validate with pyangbind becuase it will be validated at check_conflict_on_edit
- return indata
-
def _validate_package_folders(self, storage_params, folder, file=None):
if not storage_params or not storage_params.get("pkg-dir"):
return False
"""
super().delete_extra(session, _id, db_content, not_send_msg)
self.db.del_list("vnfpkgops", {"vnfPkgId": _id})
+
+ def sol005_projection(self, data):
+ data["onboardingState"] = data["_admin"]["onboardingState"]
+ data["operationalState"] = data["_admin"]["operationalState"]
+ data["usageState"] = data["_admin"]["usageState"]
+
+ links = {}
+ links["self"] = {"href": "/vnfpkgm/v1/vnf_packages/{}".format(data["_id"])}
+ links["vnfd"] = {"href": "/vnfpkgm/v1/vnf_packages/{}/vnfd".format(data["_id"])}
+ links["packageContent"] = {"href": "/vnfpkgm/v1/vnf_packages/{}/package_content".format(data["_id"])}
+ data["_links"] = links
+
+ return super().sol005_projection(data)
class NsdTopic(DescriptorTopic):
return clean_indata
def _validate_input_new(self, indata, storage_params, force=False):
+ indata.pop("nsdOnboardingState", None)
+ indata.pop("nsdOperationalState", None)
+ indata.pop("nsdUsageState", None)
+
+ indata.pop("links", None)
+
indata = self.pyangbind_validation("nsds", indata, force)
# Cross references validation in the descriptor
# TODO validata that if contains cloud-init-file or charms, have artifacts _admin.storage."pkg-dir" is not none
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
return indata
- def _validate_input_edit(self, indata, force=False):
+ def _validate_input_edit(self, indata, content, force=False):
# not needed to validate with pyangbind becuase it will be validated at check_conflict_on_edit
+ """
+ indata looks as follows:
+ - In the new case (conformant)
+ {'nsdOperationalState': 'DISABLED', 'userDefinedData': {'id': 'string23',
+ '_id': 'c6ddc544-cede-4b94-9ebe-be07b298a3c1', 'name': 'simon46'}}
+ - In the old case (backwards-compatible)
+ {'id': 'string23', '_id': 'c6ddc544-cede-4b94-9ebe-be07b298a3c1', 'name': 'simon46'}
+ """
+ if "_admin" not in indata:
+ indata["_admin"] = {}
+
+ if "nsdOperationalState" in indata:
+ if indata["nsdOperationalState"] in ("ENABLED", "DISABLED"):
+ indata["_admin"]["operationalState"] = indata.pop("nsdOperationalState")
+ else:
+ raise EngineException("State '{}' is not a valid operational state"
+ .format(indata["nsdOperationalState"]),
+ http_code=HTTPStatus.BAD_REQUEST)
+
+ # In the case of user defined data, we need to put the data in the root of the object
+ # to preserve current expected behaviour
+ if "userDefinedData" in indata:
+ data = indata.pop("userDefinedData")
+ if type(data) == dict:
+ indata["_admin"]["userDefinedData"] = data
+ else:
+ raise EngineException("userDefinedData should be an object, but is '{}' instead"
+ .format(type(data)),
+ http_code=HTTPStatus.BAD_REQUEST)
+ if ("operationalState" in indata["_admin"] and
+ content["_admin"]["operationalState"] == indata["_admin"]["operationalState"]):
+ raise EngineException("nsdOperationalState already {}".format(content["_admin"]["operationalState"]),
+ http_code=HTTPStatus.CONFLICT)
return indata
def _check_descriptor_dependencies(self, session, descriptor):
if self.db.get_list("nsts", _filter):
raise EngineException("There is at least one NetSlice Template referencing this descriptor",
http_code=HTTPStatus.CONFLICT)
+
+ def sol005_projection(self, data):
+ data["nsdOnboardingState"] = data["_admin"]["onboardingState"]
+ data["nsdOperationalState"] = data["_admin"]["operationalState"]
+ data["nsdUsageState"] = data["_admin"]["usageState"]
+
+ links = {}
+ links["self"] = {"href": "/nsd/v1/ns_descriptors/{}".format(data["_id"])}
+ links["nsd_content"] = {"href": "/nsd/v1/ns_descriptors/{}/nsd_content".format(data["_id"])}
+ data["_links"] = links
+
+ return super().sol005_projection(data)
class NstTopic(DescriptorTopic):
topic = "nsts"
topic_msg = "nst"
+ quota_name = "slice_templates"
def __init__(self, db, fs, msg, auth):
DescriptorTopic.__init__(self, db, fs, msg, auth)
clean_indata = clean_indata['nst:nst'][0]
return clean_indata
- def _validate_input_edit(self, indata, force=False):
- # TODO validate with pyangbind, serialize
- return indata
-
def _validate_input_new(self, indata, storage_params, force=False):
+ indata.pop("onboardingState", None)
+ indata.pop("operationalState", None)
+ indata.pop("usageState", None)
indata = self.pyangbind_validation("nsts", indata, force)
return indata.copy()
raise EngineException("there is at least one Netslice Instance using this descriptor",
http_code=HTTPStatus.CONFLICT)
+ def sol005_projection(self, data):
+ data["onboardingState"] = data["_admin"]["onboardingState"]
+ data["operationalState"] = data["_admin"]["operationalState"]
+ data["usageState"] = data["_admin"]["usageState"]
+
+ links = {}
+ links["self"] = {"href": "/nst/v1/netslice_templates/{}".format(data["_id"])}
+ links["nst"] = {"href": "/nst/v1/netslice_templates/{}/nst".format(data["_id"])}
+ data["_links"] = links
+
+ return super().sol005_projection(data)
+
class PduTopic(BaseTopic):
topic = "pdus"
topic_msg = "pdu"
+ quota_name = "pduds"
schema_new = pdu_new_schema
schema_edit = pdu_edit_schema