search_dict = {
"vnfds": ("vnfrs", "vnfd-id"),
"nsds": ("nsrs", "nsd-id"),
+ "ns_config_template": ("ns_config_template", "_id"),
}
if db_collection not in search_dict:
:param not_send_msg: To not send message (False) or store content (list) instead
:return: operation id (None if there is not operation), raise exception if error or not found, conflict, ...
"""
-
# To allow addressing projects and users by name AS WELL AS by _id
if not self.multiproject:
filter_q = {}
filter_q = self._get_project_filter(session)
filter_q[self.id_field(self.topic, _id)] = _id
item_content = self.db.get_one(self.topic, filter_q)
+ nsd_id = item_content.get("_id")
self.check_conflict_on_del(session, _id, item_content)
+
+ # While deteling ns descriptor associated ns config template should also get deleted.
+ if self.topic == "nsds":
+ ns_config_template_content = self.db.get_list(
+ "ns_config_template", {"nsdId": _id}
+ )
+ for template_content in ns_config_template_content:
+ if template_content is not None:
+ if template_content.get("nsdId") == nsd_id:
+ ns_config_template_id = template_content.get("_id")
+ self.db.del_one("ns_config_template", {"nsdId": nsd_id})
+ self.delete_extra(
+ session,
+ ns_config_template_id,
+ template_content,
+ not_send_msg=not_send_msg,
+ )
if dry_run:
return None
pdu_edit_schema,
validate_input,
vnfpkgop_new_schema,
+ ns_config_template,
+ vnf_schema,
+ vld_schema,
+ additional_params_for_vnf,
)
from osm_nbi.base_topic import (
BaseTopic,
rollback.append({"topic": self.topic, "_id": vnfpkgop_id})
self.msg.write(self.topic_msg, operation, vnfpkgop_desc)
return vnfpkgop_id, None
+
+
+class NsConfigTemplateTopic(DescriptorTopic):
+ topic = "ns_config_template"
+ topic_msg = "nsd"
+ schema_new = ns_config_template
+ instantiation_params = {
+ "vnf": vnf_schema,
+ "vld": vld_schema,
+ "additionalParamsForVnf": additional_params_for_vnf,
+ }
+
+ def __init__(self, db, fs, msg, auth):
+ super().__init__(db, fs, msg, auth)
+
+ def check_conflict_on_del(self, session, _id, db_content):
+ """
+ Check that there is not any NSR that uses this NS CONFIG TEMPLATE. Only NSRs belonging to this project are considered.
+ :param session: contains "username", "admin", "force", "public", "project_id", "set_project"
+ :param _id: ns config template internal id
+ :param db_content: The database content of the _id
+ :return: None or raises EngineException with the conflict
+ """
+ if session["force"]:
+ return
+ descriptor = db_content
+ descriptor_id = descriptor.get("nsdId")
+ if not descriptor_id: # empty nsd not uploaded
+ return
+
+ # check NS CONFIG TEMPLATE used by NS
+ ns_config_template_id = _id
+ self.logger.info("The id is : {}".format(_id))
+ if self.db.get_list(
+ "nsrs", {"instantiate_params.nsConfigTemplateId": ns_config_template_id}
+ ):
+ raise EngineException(
+ "There is at least one NS instance using this template",
+ http_code=HTTPStatus.CONFLICT,
+ )
+
+ def check_unique_template_name(self, edit_content, _id, session):
+ """
+ Check whether the name of the template is unique or not
+ """
+
+ if edit_content.get("name"):
+ name = edit_content.get("name")
+ db_content = self.db.get_one(
+ "ns_config_template", {"name": name}, fail_on_empty=False
+ )
+ if db_content is not None:
+ if db_content.get("_id") == _id:
+ if db_content.get("name") == name:
+ return
+ elif db_content.get("_id") != _id:
+ raise EngineException(
+ "{} of the template already exist".format(name)
+ )
+ else:
+ return
+
+ def check_conflict_on_edit(self, session, final_content, edit_content, _id):
+ """
+ Check the input data format
+ And the edit content data too.
+ """
+ final_content = super().check_conflict_on_edit(
+ session, final_content, edit_content, _id
+ )
+ db_content_id = self.db.get_one(
+ "ns_config_template", {"_id": _id}, fail_on_empty=False
+ )
+ if not (
+ db_content_id.get("name")
+ and db_content_id.get("nsdId")
+ and db_content_id.get("config")
+ ):
+ validate_input(edit_content, self.schema_new)
+
+ try:
+ for key, value in edit_content.items():
+ if key == "name":
+ self.check_unique_template_name(edit_content, _id, session)
+ elif key == "nsdId":
+ ns_config_template = self.db.get_one(
+ "ns_config_template", {"_id": _id}, fail_on_empty=False
+ )
+ if not ns_config_template.get("nsdId"):
+ pass
+ else:
+ raise EngineException("Nsd id cannot be edited")
+ elif key == "config":
+ edit_content_param = edit_content.get("config")
+ for key, value in edit_content_param.items():
+ param = key
+ param_content = value
+ validate_input(param_content, self.instantiation_params[param])
+ return final_content
+ except Exception as e:
+ raise EngineException(
+ "Error in instantiation parameters validation: {}".format(str(e)),
+ http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
+ )
PduTopic,
NstTopic,
VnfPkgOpTopic,
+ NsConfigTemplateTopic,
)
from osm_nbi.instance_topics import (
NsrTopic,
"vnf_instances": VnfInstances,
"vnflcmops": VnfLcmOpTopic,
"vnflcm_subscriptions": VnflcmSubscriptionsTopic,
+ "nsconfigtemps": NsConfigTemplateTopic,
# [NEW_TOPIC]: add an entry here
# "pm_jobs": PmJobsTopic will be added manually because it needs other parameters
}
"nsds", {"_id": used_nsd_id}, {"_admin.usageState": "NOT_IN_USE"}
)
+ # Set NS CONFIG TEMPLATE usageState
+ if nsr.get("instantiate_params", {}).get("nsConfigTemplateId"):
+ nsconfigtemplate_id = nsr.get("instantiate_params", {}).get(
+ "nsConfigTemplateId"
+ )
+ nsconfigtemplate_list = self.db.get_one(
+ "nsrs",
+ {"instantiate_params.nsConfigTemplateId": nsconfigtemplate_id},
+ fail_on_empty=False,
+ fail_on_more=False,
+ )
+ if not nsconfigtemplate_list:
+ self.db.set_one(
+ "ns_config_template",
+ {"_id": nsconfigtemplate_id},
+ {"_admin.usageState": "NOT_IN_USE"},
+ )
+
# Set VNFD usageState
used_vnfd_id_list = nsr.get("vnfd-id")
if used_vnfd_id_list:
nsd = self._get_nsd_from_db(ns_request["nsdId"], session)
ns_k8s_namespace = self._get_ns_k8s_namespace(nsd, ns_request, session)
+ # Uploading the instantiation parameters to ns_request from ns config template
+ if ns_request.get("nsConfigTemplateId"):
+ step = "getting ns_config_template is='{}' from database".format(
+ ns_request.get("nsConfigTemplateId")
+ )
+ ns_config_template_db = self._get_nsConfigTemplate_from_db(
+ ns_request.get("nsConfigTemplateId"), session
+ )
+ ns_config_params = ns_config_template_db.get("config")
+ for key, value in ns_config_params.items():
+ if key == "vnf":
+ ns_request["vnf"] = ns_config_params.get("vnf")
+ elif key == "additionalParamsForVnf":
+ ns_request["additionalParamsForVnf"] = ns_config_params.get(
+ "additionalParamsForVnf"
+ )
+ elif key == "additionalParamsForNs":
+ ns_request["additionalParamsForNs"] = ns_config_params.get(
+ "additionalParamsForNs"
+ )
+ elif key == "vld":
+ ns_request["vld"] = ns_config_params.get("vld")
+ step = "checking ns_config_templateOperationalState"
+ self._check_ns_config_template_operational_state(
+ ns_config_template_db, ns_request
+ )
+
+ step = "Updating NSCONFIG TEMPLATE usageState"
+ update_descriptor_usage_state(
+ ns_config_template_db, "ns_config_template", self.db
+ )
+
step = "checking nsdOperationalState"
self._check_nsd_operational_state(nsd, ns_request)
_filter["_id"] = nsd_id
return self.db.get_one("nsds", _filter)
+ def _get_nsConfigTemplate_from_db(self, nsConfigTemplate_id, session):
+ _filter = self._get_project_filter(session)
+ _filter["_id"] = nsConfigTemplate_id
+ ns_config_template_db = self.db.get_one(
+ "ns_config_template", _filter, fail_on_empty=False
+ )
+ return ns_config_template_db
+
def _get_vnfd_from_db(self, vnfd_id, session):
_filter = self._get_project_filter(session)
_filter["id"] = vnfd_id
http_code=HTTPStatus.CONFLICT,
)
+ def _check_ns_config_template_operational_state(
+ self, ns_config_template_db, ns_request
+ ):
+ if ns_config_template_db["_admin"]["operationalState"] == "DISABLED":
+ raise EngineException(
+ "ns_config_template with id '{}' is DISABLED, and thus cannot be used to create "
+ "a network service".format(ns_request["nsConfigTemplateId"]),
+ http_code=HTTPStatus.CONFLICT,
+ )
+
def _get_ns_k8s_namespace(self, nsd, ns_request, session):
additional_params, _ = self._format_additional_params(
ns_request, descriptor=nsd
/nsd_content O5 O5
/nsd O
/artifacts[/<artifactPath>] O
+ /ns_config_template O O
+ /<nsConfigTemplateId> O O
+ /template_content O O
/pnf_descriptors 5 5
/<pnfdInfoId> 5 5 5
/pnfd_content 5 5
},
},
},
+ "ns_config_template": {
+ "METHODS": ("GET", "POST"),
+ "ROLE_PERMISSION": "ns_config_template:content:",
+ "<ID>": {
+ "METHODS": ("GET", "DELETE"),
+ "ROLE_PERMISSION": "ns_config_template:id:",
+ "template_content": {
+ "METHODS": ("GET", "PUT"),
+ "ROLE_PERMISSION": "ns_config_template:id:content:",
+ },
+ },
+ },
"pnf_descriptors": {
"TODO": ("GET", "POST"),
"<ID>": {
if main_topic == "nsd":
engine_topic = "nsds"
+ if topic == "ns_config_template":
+ engine_topic = "nsconfigtemps"
elif main_topic == "vnfpkgm":
engine_topic = "vnfds"
if topic == "vnfpkg_op_occs":
"nsd",
"nst",
"nst_content",
+ "ns_config_template",
):
if item in ("vnfd", "nsd", "nst"):
path = "$DESCRIPTOR"
"ns_descriptors_content",
"vnf_packages_content",
"netslice_templates_content",
+ "ns_config_template",
):
_id = cherrypy.request.headers.get("Transaction-Id")
if not _id:
HTTPStatus.BAD_REQUEST,
)
if (
- item in ("nsd_content", "package_content", "nst_content")
+ item
+ in (
+ "nsd_content",
+ "package_content",
+ "nst_content",
+ "template_content",
+ )
and method == "PUT"
):
completed = self.engine.upload_content(
},
}
+vnf_schema = {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "member-vnf-index": name_schema,
+ "vimAccountId": id_schema,
+ "vdu": {
+ "type": "array",
+ "minItems": 1,
+ "items": ns_instantiate_vdu,
+ },
+ "internal-vld": {
+ "type": "array",
+ "minItems": 1,
+ "items": ns_instantiate_internal_vld,
+ },
+ },
+ "required": ["member-vnf-index"],
+ "minProperties": 2,
+ "additionalProperties": False,
+ },
+}
+
+vld_schema = {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": string_schema,
+ "vim-network-name": {"oneOf": [string_schema, object_schema]},
+ "vim-network-id": {"oneOf": [string_schema, object_schema]},
+ "ns-net": object_schema,
+ "wimAccountId": {"oneOf": [id_schema, bool_schema, null_schema]},
+ "ip-profile": ip_profile_schema,
+ "provider-network": provider_network_schema,
+ "vnfd-connection-point-ref": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "properties": {
+ "member-vnf-index-ref": name_schema,
+ "vnfd-connection-point-ref": name_schema,
+ "ip-address": {"oneOf": [ip_schema, ipv6_schema]},
+ # "mac-address": mac_schema,
+ },
+ "required": [
+ "member-vnf-index-ref",
+ "vnfd-connection-point-ref",
+ ],
+ "minProperties": 3,
+ "additionalProperties": False,
+ },
+ },
+ },
+ "required": ["name"],
+ "additionalProperties": False,
+ },
+}
+
+ns_config_template = {
+ "title": " ns config template input schema",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "name": string_schema,
+ "nsdId": id_schema,
+ "config": object_schema,
+ },
+ "required": ["name", "nsdId", "config"],
+ "additionalProperties": False,
+}
+
ns_instantiate = {
"title": "ns action instantiate input schema",
"$schema": "http://json-schema.org/draft-04/schema#",
"nsDescription": {"oneOf": [description_schema, null_schema]},
"nsdId": id_schema,
"vimAccountId": id_schema,
+ "nsConfigTemplateId": id_schema,
"wimAccountId": {"oneOf": [id_schema, bool_schema, null_schema]},
"placement-engine": string_schema,
"placement-constraints": object_schema,
"timeout_ns_deploy": integer1_schema,
"nsr_id": id_schema,
"vduImage": name_schema,
- "vnf": {
- "type": "array",
- "minItems": 1,
- "items": {
- "type": "object",
- "properties": {
- "member-vnf-index": name_schema,
- "vimAccountId": id_schema,
- "vdu": {
- "type": "array",
- "minItems": 1,
- "items": ns_instantiate_vdu,
- },
- "internal-vld": {
- "type": "array",
- "minItems": 1,
- "items": ns_instantiate_internal_vld,
- },
- },
- "required": ["member-vnf-index"],
- "minProperties": 2,
- "additionalProperties": False,
- },
- },
- "vld": {
- "type": "array",
- "minItems": 1,
- "items": {
- "type": "object",
- "properties": {
- "name": string_schema,
- "vim-network-name": {"oneOf": [string_schema, object_schema]},
- "vim-network-id": {"oneOf": [string_schema, object_schema]},
- "ns-net": object_schema,
- "wimAccountId": {"oneOf": [id_schema, bool_schema, null_schema]},
- "ip-profile": ip_profile_schema,
- "provider-network": provider_network_schema,
- "vnfd-connection-point-ref": {
- "type": "array",
- "minItems": 1,
- "items": {
- "type": "object",
- "properties": {
- "member-vnf-index-ref": name_schema,
- "vnfd-connection-point-ref": name_schema,
- "ip-address": {"oneOf": [ip_schema, ipv6_schema]},
- # "mac-address": mac_schema,
- },
- "required": [
- "member-vnf-index-ref",
- "vnfd-connection-point-ref",
- ],
- "minProperties": 3,
- "additionalProperties": False,
- },
- },
- },
- "required": ["name"],
- "additionalProperties": False,
- },
- },
+ "vnf": vnf_schema,
+ "vld": vld_schema,
},
"required": ["nsName", "nsdId", "vimAccountId"],
"additionalProperties": False,
"vim_accounts": vim_account_edit_schema,
"sdns": sdn_edit_schema,
"pdus": pdu_edit_schema,
+ "vnf": vnf_schema,
+ "vld": vld_schema,
+ "additionalParamsForVnf": additional_params_for_vnf,
}
# NETSLICE SCHEMAS