import yaml
import json
import importlib
+import copy
# import logging
from hashlib import md5
from osm_common.dbbase import DbException, deep_update_rfc7396
from osm_im.nst import nst as nst_im
from pyangbind.lib.serialise import pybindJSONDecoder
import pyangbind.lib.pybindJSON as pybindJSON
+from osm_nbi import utils
__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
BaseTopic.__init__(self, db, fs, msg, auth)
def check_conflict_on_edit(self, session, final_content, edit_content, _id):
- super().check_conflict_on_edit(session, final_content, edit_content, _id)
+ final_content = 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():
internal_keys[k] = final_content.pop(k)
storage_params = internal_keys["_admin"].get("storage")
serialized = self._validate_input_new(final_content, storage_params, session["force"])
+
# 1.2. modify final_content with a serialized version
- final_content.clear()
- final_content.update(serialized)
+ final_content = copy.deepcopy(serialized)
# 1.3. restore internal keys
for k, v in internal_keys.items():
final_content[k] = v
if session["force"]:
- return
+ return final_content
+
# 2. check that this id is not present
if "id" in edit_content:
_filter = self._get_project_filter(session)
+
_filter["id"] = final_content["id"]
_filter["_id.neq"] = _id
+
if self.db.get_one(self.topic, _filter, fail_on_empty=False):
raise EngineException("{} with id '{}' already exists for this project".format(self.topic[:-1],
final_content["id"]),
HTTPStatus.CONFLICT)
+ return final_content
+
@staticmethod
def format_on_new(content, project_id=None, make_public=False):
BaseTopic.format_on_new(content, project_id=project_id, make_public=make_public)
self._update_input_with_kwargs(indata, kwargs)
deep_update_rfc7396(current_desc, indata)
- self.check_conflict_on_edit(session, current_desc, indata, _id=_id)
+ current_desc = 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)
raise EngineException("ERROR: Unsupported descriptor format. Please, use an ETSI SOL006 descriptor.",
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
try:
- virtual_compute_descriptors = data.get('virtual-compute-desc')
- virtual_storage_descriptors = data.get('virtual-storage-desc')
myvnfd = etsi_nfv_vnfd.etsi_nfv_vnfd()
pybindJSONDecoder.load_ietf_json({'etsi-nfv-vnfd:vnfd': data}, None, None, obj=myvnfd,
path_helper=True, skip_unknown=force)
out = pybindJSON.dumps(myvnfd, mode="ietf")
desc_out = self._remove_envelop(yaml.safe_load(out))
desc_out = self._remove_yang_prefixes_from_descriptor(desc_out)
- if virtual_compute_descriptors:
- desc_out['virtual-compute-desc'] = virtual_compute_descriptors
- if virtual_storage_descriptors:
- desc_out['virtual-storage-desc'] = virtual_storage_descriptors
- return desc_out
+ return utils.deep_update_dict(data, desc_out)
except Exception as e:
raise EngineException("Error in pyangbind validation: {}".format(str(e)),
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
return clean_indata
def check_conflict_on_edit(self, session, final_content, edit_content, _id):
- super().check_conflict_on_edit(session, final_content, edit_content, _id)
+ final_content = super().check_conflict_on_edit(session, final_content, edit_content, _id)
# set type of vnfd
contains_pdu = False
elif contains_vdu:
final_content["_admin"]["type"] = "vnfd"
# if neither vud nor pdu do not fill type
+ return final_content
def check_conflict_on_del(self, session, _id, db_content):
"""
# check vnfrs using this vnfd
_filter["vnfd-id"] = _id
if self.db.get_list("vnfrs", _filter):
- raise EngineException("There is at least one VNF using this descriptor", http_code=HTTPStatus.CONFLICT)
+ raise EngineException("There is at least one VNF instance using this descriptor",
+ http_code=HTTPStatus.CONFLICT)
# check NSD referencing this VNFD
del _filter["vnfd-id"]
- _filter["constituent-vnfd.ANYINDEX.vnfd-id-ref"] = descriptor_id
+ _filter["vnfd-id"] = descriptor_id
if self.db.get_list("nsds", _filter):
- raise EngineException("There is at least one NSD referencing this descriptor",
+ raise EngineException("There is at least one NS package referencing this descriptor",
http_code=HTTPStatus.CONFLICT)
def _validate_input_new(self, indata, storage_params, force=False):
for vdu in get_iterable(indata.get("vdu")):
self.validate_vdu_internal_connection_points(vdu)
- self._validate_vdu_charms_in_package(storage_params, vdu, indata)
self._validate_vdu_cloud_init_in_package(storage_params, vdu, indata)
+ self._validate_vdu_charms_in_package(storage_params, indata)
self._validate_vnf_charms_in_package(storage_params, indata)
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
# TODO: Validate k8s-cluster-net points to a valid k8s-cluster:nets ?
- def _validate_vdu_charms_in_package(self, storage_params, vdu, indata):
- if not vdu.get("vdu-configuration"):
- return
- for vdu_configuration in get_iterable(indata.get("vdu-configuration")):
- if vdu_configuration.get("juju"):
- if not self._validate_package_folders(storage_params, 'charms'):
- raise EngineException("Charm defined in vnf[id={}] but not present in "
- "package".format(indata["id"]))
+ def _validate_vdu_charms_in_package(self, storage_params, indata):
+ for df in indata["df"]:
+ if "lcm-operations-configuration" in df and "operate-vnf-op-config" in df["lcm-operations-configuration"]:
+ configs = df["lcm-operations-configuration"]["operate-vnf-op-config"].get("day1-2", [])
+ vdus = df.get("vdu-profile", [])
+ for vdu in vdus:
+ for config in configs:
+ if config["id"] == vdu["id"] and utils.find_in_list(
+ config.get("execution-environment-list", []),
+ lambda ee: "juju" in ee
+ ):
+ if not self._validate_package_folders(storage_params, 'charms'):
+ raise EngineException("Charm defined in vnf[id={}] but not present in "
+ "package".format(indata["id"]))
def _validate_vdu_cloud_init_in_package(self, storage_params, vdu, indata):
if not vdu.get("cloud-init-file"):
"package".format(indata["id"], vdu["id"]))
def _validate_vnf_charms_in_package(self, storage_params, indata):
- if not indata.get("vnf-configuration"):
- return
- for vnf_configuration in get_iterable(indata.get("vnf-configuration")):
- if vnf_configuration.get("juju"):
- if not self._validate_package_folders(storage_params, 'charms'):
- raise EngineException("Charm defined in vnf[id={}] but not present in "
- "package".format(indata["id"]))
+ # Get VNF configuration through new container
+ for deployment_flavor in indata.get('df', []):
+ if "lcm-operations-configuration" not in deployment_flavor:
+ return
+ if "operate-vnf-op-config" not in deployment_flavor["lcm-operations-configuration"]:
+ return
+ for day_1_2_config in deployment_flavor["lcm-operations-configuration"]["operate-vnf-op-config"]["day1-2"]:
+ if day_1_2_config["id"] == indata["id"]:
+ if utils.find_in_list(
+ day_1_2_config.get("execution-environment-list", []),
+ lambda ee: "juju" in ee
+ ):
+ if not self._validate_package_folders(storage_params, 'charms'):
+ raise EngineException("Charm defined in vnf[id={}] but not present in "
+ "package".format(indata["id"]))
def _validate_package_folders(self, storage_params, folder, file=None):
if not storage_params or not storage_params.get("pkg-dir"):
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
for sca in get_iterable(sa.get("scaling-config-action")):
- if not indata.get("vnf-configuration"):
- raise EngineException("'vnf-configuration' not defined in the descriptor but it is referenced "
- "by df[id='{}']:scaling-aspect[id='{}']:scaling-config-action"
+ if "lcm-operations-configuration" not in df \
+ or "operate-vnf-op-config" not in df["lcm-operations-configuration"] \
+ or not utils.find_in_list(
+ df["lcm-operations-configuration"]["operate-vnf-op-config"].get("day1-2", []),
+ lambda config: config["id"] == indata["id"]):
+ raise EngineException("'day1-2 configuration' not defined in the descriptor but it is "
+ "referenced by df[id='{}']:scaling-aspect[id='{}']:scaling-config-action"
.format(df["id"], sa["id"]),
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
- for configuration in get_iterable(indata["vnf-configuration"]):
+ for configuration in get_iterable(
+ df["lcm-operations-configuration"]["operate-vnf-op-config"].get("day1-2", [])
+ ):
for primitive in get_iterable(configuration.get("config-primitive")):
if primitive["name"] == sca["vnf-config-primitive-name-ref"]:
break
else:
raise EngineException("df[id='{}']:scaling-aspect[id='{}']:scaling-config-action:vnf-"
"config-primitive-name-ref='{}' does not match any "
- "vnf-configuration:config-primitive:name"
+ "day1-2 configuration:config-primitive:name"
.format(df["id"], sa["id"], sca["vnf-config-primitive-name-ref"]),
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
http_code=HTTPStatus.UNPROCESSABLE_ENTITY)
def check_conflict_on_edit(self, session, final_content, edit_content, _id):
- super().check_conflict_on_edit(session, final_content, edit_content, _id)
+ final_content = super().check_conflict_on_edit(session, final_content, edit_content, _id)
self._check_descriptor_dependencies(session, final_content)
+ return final_content
+
def check_conflict_on_del(self, session, _id, db_content):
"""
Check that there is not any NSR that uses this NSD. Only NSRs belonging to this project are considered. Note
_filter = self._get_project_filter(session)
_filter["nsd-id"] = _id
if self.db.get_list("nsrs", _filter):
- raise EngineException("There is at least one NS using this descriptor", http_code=HTTPStatus.CONFLICT)
+ raise EngineException("There is at least one NS instance using this descriptor",
+ http_code=HTTPStatus.CONFLICT)
# check NSD referenced by NST
del _filter["nsd-id"]
"existing nsd".format(nsd_id), http_code=HTTPStatus.CONFLICT)
def check_conflict_on_edit(self, session, final_content, edit_content, _id):
- super().check_conflict_on_edit(session, final_content, edit_content, _id)
+ final_content = super().check_conflict_on_edit(session, final_content, edit_content, _id)
self._check_descriptor_dependencies(session, final_content)
+ return final_content
def check_conflict_on_del(self, session, _id, db_content):
"""
_filter = self._get_project_filter(session)
_filter["vdur.pdu-id"] = _id
if self.db.get_list("vnfrs", _filter):
- raise EngineException("There is at least one VNF using this PDU", http_code=HTTPStatus.CONFLICT)
+ raise EngineException("There is at least one VNF instance using this PDU", http_code=HTTPStatus.CONFLICT)
class VnfPkgOpTopic(BaseTopic):