Adding NSI operations (Create, Read, Delete)
Change-Id: I013e3d54014ed266e6232e5410ad53ddf8df70ea
Signed-off-by: Felipe Vicens <felipe.vicens@atos.net>
diff --git a/Dockerfile.local b/Dockerfile.local
index da13878..0d2a3d6 100644
--- a/Dockerfile.local
+++ b/Dockerfile.local
@@ -6,7 +6,7 @@
WORKDIR /app/NBI/osm_nbi
# Copy the current directory contents into the container at /app
-ADD . /app/NBI
+#ADD . /app
RUN apt-get update && apt-get install -y git python3 python3-jsonschema \
python3-pymongo python3-yaml python3-pip python3-keystoneclient \
@@ -80,6 +80,8 @@
#ENV OSMNBI_AUTHENTICATION_SERVICE_PASSWORD nbi
#ENV OSMNBI_AUTHENTICATION_SERVICE_PROJECT service
+ADD . /app/NBI
+
# Run app.py when the container launches
CMD ["python3", "nbi.py"]
diff --git a/osm_nbi/descriptor_topics.py b/osm_nbi/descriptor_topics.py
index 9e367c9..3ace489 100644
--- a/osm_nbi/descriptor_topics.py
+++ b/osm_nbi/descriptor_topics.py
@@ -40,7 +40,7 @@
BaseTopic.format_on_new(content, project_id=project_id, make_public=make_public)
content["_admin"]["onboardingState"] = "CREATED"
content["_admin"]["operationalState"] = "DISABLED"
- content["_admin"]["usageSate"] = "NOT_IN_USE"
+ content["_admin"]["usageState"] = "NOT_IN_USE"
def delete(self, session, _id, force=False, dry_run=False):
"""
@@ -657,16 +657,6 @@
clean_indata = clean_indata['nst'][0]
return clean_indata
- def _validate_input_new(self, indata, force=False):
- # transform netslice-subnet:nsd-ref to string
- if indata.get("netslice-subnet"):
- for nsd_ref in indata["netslice-subnet"]:
- if "nsd-ref" in nsd_ref:
- nsd_ref["nsd-ref"] = str(nsd_ref["nsd-ref"])
-
- # TODO validate with pyangbind, serialize
- return indata
-
def _validate_input_edit(self, indata, force=False):
# TODO validate with pyangbind, serialize
return indata
@@ -698,15 +688,21 @@
Check that there is not any NSIR that uses this NST. Only NSIRs belonging to this project are considered. Note
that NST can be public and be used by other projects.
:param session:
- :param _id: nsd internal id
+ :param _id: nst internal id
:param force: Avoid this checking
:return: None or raises EngineException with the conflict
"""
# TODO: Check this method
if force:
return
+ # Get Network Slice Template from Database
_filter = self._get_project_filter(session, write=False, show_all=False)
- _filter["nst"] = _id
+ _filter["_id"] = _id
+ nst = self.db.get_one("nst", _filter)
+
+ # Search NSIs using NST via nst-ref
+ _filter = self._get_project_filter(session, write=False, show_all=False)
+ _filter["nst-ref"] = nst["id"]
if self.db.get_list("nsis", _filter):
raise EngineException("There is some NSIS that depends on this NST", http_code=HTTPStatus.CONFLICT)
@@ -725,7 +721,7 @@
BaseTopic.format_on_new(content, project_id=None, make_public=make_public)
content["_admin"]["onboardingState"] = "CREATED"
content["_admin"]["operationalState"] = "DISABLED"
- content["_admin"]["usageSate"] = "NOT_IN_USE"
+ content["_admin"]["usageState"] = "NOT_IN_USE"
def check_conflict_on_del(self, session, _id, force=False):
if force:
diff --git a/osm_nbi/engine.py b/osm_nbi/engine.py
index 3de3d15..4713b89 100644
--- a/osm_nbi/engine.py
+++ b/osm_nbi/engine.py
@@ -9,7 +9,7 @@
from base_topic import EngineException, versiontuple
from admin_topics import UserTopic, ProjectTopic, VimAccountTopic, SdnTopic
from descriptor_topics import VnfdTopic, NsdTopic, PduTopic, NstTopic
-from instance_topics import NsrTopic, VnfrTopic, NsLcmOpTopic, NsiTopic
+from instance_topics import NsrTopic, VnfrTopic, NsLcmOpTopic, NsiTopic, NsiLcmOpTopic
from base64 import b64encode
from os import urandom
@@ -31,6 +31,7 @@
"users": UserTopic,
"projects": ProjectTopic,
"nsis": NsiTopic,
+ "nsilcmops": NsiLcmOpTopic
# [NEW_TOPIC]: add an entry here
}
diff --git a/osm_nbi/html_out.py b/osm_nbi/html_out.py
index e9237e9..8d3baab 100644
--- a/osm_nbi/html_out.py
+++ b/osm_nbi/html_out.py
@@ -25,6 +25,7 @@
<a href="/osm/nsd/v1/ns_descriptors">NSDs </a>
<a href="/osm/nslcm/v1/ns_instances">NSs </a>
<a href="/osm/nst/v1/netslice_templates">NSTDs </a>
+ <a href="/osm/nsilcm/v1/netslice_instances">NSIs </a>
<a href="/osm/admin/v1/users">USERs </a>
<a href="/osm/admin/v1/projects">PROJECTs </a>
<a href="/osm/admin/v1/tokens">TOKENs </a>
@@ -102,6 +103,15 @@
</form>
"""
+html_nsilcmop_body = """
+<a href="/osm/nsilcm/v1/nsi_lcm_op_occs?nsiInstanceId={id}">nsilcm operations </a>
+<form action="/osm/nsilcm/v1/netslice_instances/{id}/terminate" method="post" enctype="multipart/form-data">
+ <h3> <table style="border: 0;"> <tr>
+ <td> <input type="submit" value="Terminate"/> </td>
+ </tr> </table> </h3>
+</form>
+"""
+
def format(data, request, response, session):
"""
@@ -145,6 +155,10 @@
request.path_info.startswith("/nslcm/v1/ns_instances/"):
_id = request.path_info[request.path_info.rfind("/")+1:]
body += html_nslcmop_body.format(id=_id)
+ elif request.path_info.startswith("/nsilcm/v1/netslice_instances_content/") or \
+ request.path_info.startswith("/nsilcm/v1/netslice_instances/"):
+ _id = request.path_info[request.path_info.rfind("/")+1:]
+ body += html_nsilcmop_body.format(id=_id)
body += "<pre>" + html_escape(yaml.safe_dump(data, explicit_start=True, indent=4, default_flow_style=False)) + \
"</pre>"
elif data is None:
diff --git a/osm_nbi/instance_topics.py b/osm_nbi/instance_topics.py
index 4228bc5..41187dc 100644
--- a/osm_nbi/instance_topics.py
+++ b/osm_nbi/instance_topics.py
@@ -5,7 +5,7 @@
from http import HTTPStatus
from time import time
from copy import copy, deepcopy
-from validation import validate_input, ValidationError, ns_instantiate, ns_action, ns_scale
+from validation import validate_input, ValidationError, ns_instantiate, ns_action, ns_scale, nsi_instantiate
from base_topic import BaseTopic, EngineException, get_iterable
from descriptor_topics import DescriptorTopic
@@ -66,7 +66,7 @@
self.db.del_list("vnfrs", {"nsr-id-ref": _id})
# set all used pdus as free
self.db.set_list("pdus", {"_admin.usage.nsr_id": _id},
- {"_admin.usageSate": "NOT_IN_USE", "_admin.usage": None})
+ {"_admin.usageState": "NOT_IN_USE", "_admin.usage": None})
self._send_msg("deleted", {"_id": _id})
return v
@@ -266,17 +266,6 @@
def __init__(self, db, fs, msg):
BaseTopic.__init__(self, db, fs, msg)
- def _validate_input_new(self, input, force=False):
- """
- Validates input user content for a new entry. It uses jsonschema for each type or operation.
- :param input: user input content for the new topic
- :param force: may be used for being more tolerant
- :return: The same input content, or a changed version of it.
- """
- if self.schema_new:
- validate_input(input, self.schema_new)
- return input
-
def _check_ns_operation(self, session, nsr, operation, indata):
"""
Check that user has enter right parameters for the operation
@@ -432,7 +421,7 @@
pdu_filter["vim.vim_accounts"] = vim_account
pdu_filter["type"] = pdu_type
pdu_filter["_admin.operationalState"] = "ENABLED"
- pdu_filter["_admin.usageSate"] = "NOT_IN_USE",
+ pdu_filter["_admin.usageState"] = "NOT_IN_USE",
# TODO feature 1417: "shared": True,
available_pdus = self.db.get_list("pdus", pdu_filter)
@@ -462,7 +451,7 @@
"_admin.usage.vdur": None,
}
self.db.set_one("pdus", {"_id": pdu["_id"]},
- {"_admin.usageSate": "IN_USE",
+ {"_admin.usageState": "IN_USE",
"_admin.usage.vnfr_id": vnfr["_id"],
"_admin.usage.nsr_id": vnfr["nsr-id-ref"],
"_admin.usage.vdur": vdur["vdu-id-ref"]}
@@ -535,7 +524,8 @@
}
return nslcmop
- def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+ def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False,
+ slice_object=False):
"""
Performs a new operation over a ns
:param rollback: list to append created items at database in case a rollback must to be done
@@ -580,7 +570,8 @@
self.format_on_new(nslcmop_desc, session["project_id"], make_public=make_public)
_id = self.db.create("nslcmops", nslcmop_desc)
rollback.append({"topic": "nslcmops", "_id": _id})
- self.msg.write("ns", operation, nslcmop_desc)
+ if not slice_object:
+ self.msg.write("ns", operation, nslcmop_desc)
return _id
except ValidationError as e:
raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY)
@@ -608,17 +599,16 @@
:param descriptor: descriptor to be inserted or edit
:return: None or raises exception
"""
- if not descriptor.get("nstdId"):
+ if not descriptor.get("nst-ref"):
return
- nstd_id = descriptor["nstdId"]
+ nstd_id = descriptor["nst-ref"]
if not self.get_item_list(session, "nsts", {"id": nstd_id}):
- raise EngineException("Descriptor error at nstdId='{}' references a non exist nstd".format(nstd_id),
+ raise EngineException("Descriptor error at nst-ref='{}' references a non exist nstd".format(nstd_id),
http_code=HTTPStatus.CONFLICT)
@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)
- content["_admin"]["nstState"] = "NOT_INSTANTIATED"
def check_conflict_on_del(self, session, _id, force=False):
if force:
@@ -642,17 +632,28 @@
BaseTopic.delete(self, session, _id, force, dry_run=True)
if dry_run:
return
+
+ # deletes NetSlice instance object
v = self.db.del_one("nsis", {"_id": _id})
- self.db.del_list("nstlcmops", {"nstInstanceId": _id})
- self.db.del_list("vnfrs", {"nsr-id-ref": _id})
- # set all used pdus as free
- self.db.set_list("pdus", {"_admin.usage.nsr_id": _id}, {"_admin.usageSate": "NOT_IN_USE", "_admin.usage": None})
+
+ # makes a temporal list of nsilcmops objects related to the _id given and deletes them from db
+ _filter = {"netsliceInstanceId": _id}
+ self.db.del_list("nsilcmops", _filter)
+
+ _filter = {"operationParams.netsliceInstanceId": _id}
+ nslcmops_list = self.db.get_list("nslcmops", _filter)
+
+ for id_item in nslcmops_list:
+ _filter = {"_id": id_item}
+ nslcmop = self.db.get_one("nslcmops", _filter)
+ nsr_id = nslcmop["operationParams"]["nsr_id"]
+ NsrTopic.delete(self, session, nsr_id, force=False, dry_run=False)
self._send_msg("deleted", {"_id": _id})
return v
def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
"""
- Creates a new nsr into database. It also creates needed vnfrs
+ Creates a new netslice instance record into database. It also creates needed nsrs and vnfrs
:param rollback: list to append the created items at database in case a rollback must be done
:param session: contains the used login username and working project
:param indata: params to be used for the nsir
@@ -671,13 +672,18 @@
step = ""
# look for nstd
+ self.logger.info(str(slice_request))
step = "getting nstd id='{}' from database".format(slice_request.get("nstdId"))
- _filter = {"_id": slice_request["nstdId"]}
+ _filter = {"id": slice_request["nstdId"]}
_filter.update(BaseTopic._get_project_filter(session, write=False, show_all=True))
nstd = self.db.get_one("nsts", _filter)
+ nstd.pop("_admin", None)
+ nstd.pop("_id", None)
nsi_id = str(uuid4())
- # now = time()
step = "filling nsi_descriptor with input data"
+
+ # "instantiation-parameters.netslice-subnet": []
+ # TODO: Equal as template for now
nsi_descriptor = {
"id": nsi_id,
"nst-ref": nstd["id"],
@@ -685,28 +691,12 @@
"netslice-subnet": []
},
"network-slice-template": nstd,
- # "nsr-ref-list": [], #TODO: not used for now...
- # "vlr-ref-list": [], #TODO: not used for now...
"_id": nsi_id,
-
- # TODO CHECK: what about the following params?
- # "admin-status": "ENABLED",
- # "description": slice_request.get("nsDescription", ""),
- # "operational-status": "init", # typedef ns-operational-
- # "config-status": "init", # typedef config-states
- # "detailed-status": "scheduled",
- # "orchestration-progress": {},
- # # {"networks": {"active": 0, "total": 0}, "vms": {"active": 0, "total": 0}},
- # "create-time": now,
- # "operational-events": [], # "id", "timestamp", "description", "event",
- # "ssh-authorized-key": slice_request.get("key-pair-ref"),
}
- # nstd["nsi_id"] = nsi_id
- # TODO: ask if we have to develop the VNFR here or we can imply call the NsrTopic() for each service to
- # instantiate.
- # Create netslice-subnet_record
+ # Creating netslice-subnet_record.
needed_nsds = {}
+ services = []
for member_ns in nstd["netslice-subnet"]:
nsd_id = member_ns["nsd-ref"]
step = "getting nstd id='{}' constituent-nsd='{}' from database".format(
@@ -716,20 +706,38 @@
nsd = DescriptorTopic.get_one_by_id(self.db, session, "nsds", nsd_id)
nsd.pop("_admin")
needed_nsds[nsd_id] = nsd
+ member_ns["_id"] = needed_nsds[nsd_id].get("_id")
+ services.append(member_ns)
else:
nsd = needed_nsds[nsd_id]
-
+ member_ns["_id"] = needed_nsds[nsd_id].get("_id")
+ services.append(member_ns)
+
step = "filling nsir nsd-id='{}' constituent-nsd='{}' from database".format(
member_ns["nsd-ref"], member_ns["id"])
- netslice_subnet_descriptor = {
- "nsName": member_ns["instantiation-parameters"]["name"],
- "nsdId": member_ns["instantiation-parameters"]["nsdId"],
- "vimAccountId": member_ns["instantiation-parameters"]["vimAccountId"]
- }
- nsi_descriptor["instantiation-parameters"]["netslice-subnet"].append(netslice_subnet_descriptor)
step = "creating nsi at database"
self.format_on_new(nsi_descriptor, session["project_id"], make_public=make_public)
+ nsi_descriptor["_admin"]["nsiState"] = "NOT_INSTANTIATED"
+
+ # creates Network Services records (NSRs)
+ step = "creating nsrs at database using NsrTopic.new()"
+ nsrs_list = []
+ for service in services:
+ indata_ns = {}
+ indata_ns["nsdId"] = service["_id"]
+ indata_ns["nsName"] = service["name"]
+ indata_ns["vimAccountId"] = indata.get("vimAccountId")
+ indata_ns["nsDescription"] = service["description"]
+ indata_ns["key-pair-ref"] = None
+ # NsrTopic(rollback, session, indata_ns, kwargs, headers, force)
+ _id_nsr = NsrTopic.new(self, rollback, session, indata_ns, kwargs, headers, force)
+ nsrs_item = {"nsrId": _id_nsr}
+ nsrs_list.append(nsrs_item)
+
+ # Adding the nsrs list to the nsi
+ nsi_descriptor["_admin"]["nsrs-detailed-list"] = nsrs_list
+ # Creating the entry in the database
self.db.create("nsis", nsi_descriptor)
rollback.append({"topic": "nsis", "_id": nsi_id})
return nsi_id
@@ -741,3 +749,141 @@
def edit(self, session, _id, indata=None, kwargs=None, force=False, content=None):
raise EngineException("Method edit called directly", HTTPStatus.INTERNAL_SERVER_ERROR)
+
+
+class NsiLcmOpTopic(BaseTopic):
+ topic = "nsilcmops"
+ topic_msg = "nsi"
+ operation_schema = { # mapping between operation and jsonschema to validate
+ "instantiate": nsi_instantiate,
+ "terminate": None
+ }
+
+ def __init__(self, db, fs, msg):
+ BaseTopic.__init__(self, db, fs, msg)
+
+ def _check_nsi_operation(self, session, nsir, operation, indata):
+ """
+ Check that user has enter right parameters for the operation
+ :param session:
+ :param operation: it can be: instantiate, terminate, action, TODO: update, heal
+ :param indata: descriptor with the parameters of the operation
+ :return: None
+ """
+ nsds = {}
+ nstd = nsir["network-slice-template"]
+
+ def check_valid_netslice_subnet_id(nsId):
+ # TODO change to vnfR (??)
+ for ns in nstd["netslice-subnet"]:
+ if nsId == ns["id"]:
+ nsd_id = ns["nsd-ref"]
+ if nsd_id not in nsds:
+ nsds[nsd_id] = self.db.get_one("nsds", {"id": nsd_id})
+ return nsds[nsd_id]
+ else:
+ raise EngineException("Invalid parameter nsId='{}' is not one of the "
+ "nst:netslice-subnet".format(nsId))
+ if operation == "instantiate":
+ # check the existance of netslice-subnet items
+ for in_nst in get_iterable(indata.get("netslice-subnet")):
+ nstd = check_valid_netslice_subnet_id(in_nst["nsdId"])
+
+ def _create_nsilcmop(self, session, netsliceInstanceId, operation, params):
+ now = time()
+ _id = str(uuid4())
+ nsilcmop = {
+ "id": _id,
+ "_id": _id,
+ "operationState": "PROCESSING", # COMPLETED,PARTIALLY_COMPLETED,FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK
+ "statusEnteredTime": now,
+ "netsliceInstanceId": netsliceInstanceId,
+ "lcmOperationType": operation,
+ "startTime": now,
+ "isAutomaticInvocation": False,
+ "operationParams": params,
+ "isCancelPending": False,
+ "links": {
+ "self": "/osm/nsilcm/v1/nsi_lcm_op_occs/" + _id,
+ "nsInstance": "/osm/nsilcm/v1/netslice_instances/" + netsliceInstanceId,
+ }
+ }
+ return nsilcmop
+
+ def new(self, rollback, session, indata=None, kwargs=None, headers=None, force=False, make_public=False):
+ """
+ Performs a new operation over a ns
+ :param rollback: list to append created items at database in case a rollback must to be done
+ :param session: contains the used login username and working project
+ :param indata: descriptor with the parameters of the operation. It must contains among others
+ nsiInstanceId: _id of the nsir to perform the operation
+ operation: it can be: instantiate, terminate, action, TODO: update, heal
+ :param kwargs: used to override the indata descriptor
+ :param headers: http request headers
+ :param force: If True avoid some dependence checks
+ :param make_public: Make the created item public to all projects
+ :return: id of the nslcmops
+ """
+ try:
+ # Override descriptor with query string kwargs
+ self._update_input_with_kwargs(indata, kwargs)
+ operation = indata["lcmOperationType"]
+ nsiInstanceId = indata["nsiInstanceId"]
+ validate_input(indata, self.operation_schema[operation])
+
+ # get nsi from nsiInstanceId
+ _filter = BaseTopic._get_project_filter(session, write=True, show_all=False)
+ _filter["_id"] = nsiInstanceId
+ nsir = self.db.get_one("nsis", _filter)
+
+ # initial checking
+ if not nsir["_admin"].get("nsiState") or nsir["_admin"]["nsiState"] == "NOT_INSTANTIATED":
+ if operation == "terminate" and indata.get("autoremove"):
+ # NSIR must be deleted
+ return self.delete(session, nsiInstanceId)
+ if operation != "instantiate":
+ raise EngineException("netslice_instance '{}' cannot be '{}' because it is not instantiated".format(
+ nsiInstanceId, operation), HTTPStatus.CONFLICT)
+ else:
+ if operation == "instantiate" and not indata.get("force"):
+ raise EngineException("netslice_instance '{}' cannot be '{}' because it is already instantiated".
+ format(nsiInstanceId, operation), HTTPStatus.CONFLICT)
+
+ # Creating all the NS_operation (nslcmop)
+ # Get service list from db
+ nsrs_list = nsir["_admin"]["nsrs-detailed-list"]
+ nslcmops = []
+ for nsr_item in nsrs_list:
+ service = self.db.get_one("nsrs", {"_id": nsr_item["nsrId"]})
+ indata_ns = {}
+ indata_ns = service["instantiate_params"]
+ indata_ns["lcmOperationType"] = operation
+ indata_ns["nsInstanceId"] = service["_id"]
+ # Including netslice_id in the ns instantiate Operation
+ indata_ns["netsliceInstanceId"] = nsiInstanceId
+ del indata_ns["key-pair-ref"]
+ nsi_NsLcmOpTopic = NsLcmOpTopic(self.db, self.fs, self.msg)
+ # Creating NS_LCM_OP with the flag slice_object=True to not trigger the service instantiation
+ # message via kafka bus
+ nslcmop = nsi_NsLcmOpTopic.new(rollback, session, indata_ns, kwargs, headers, force, slice_object=True)
+ nslcmops.append(nslcmop)
+
+ # Creates nsilcmop
+ indata["nslcmops_ids"] = nslcmops
+ self._check_nsi_operation(session, nsir, operation, indata)
+ nsilcmop_desc = self._create_nsilcmop(session, nsiInstanceId, operation, indata)
+ self.format_on_new(nsilcmop_desc, session["project_id"], make_public=make_public)
+ _id = self.db.create("nsilcmops", nsilcmop_desc)
+ rollback.append({"topic": "nsilcmops", "_id": _id})
+ self.msg.write("nsi", operation, nsilcmop_desc)
+ return _id
+ except ValidationError as e:
+ raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY)
+ # except DbException as e:
+ # raise EngineException("Cannot get nsi_instance '{}': {}".format(e), HTTPStatus.NOT_FOUND)
+
+ def delete(self, session, _id, force=False, dry_run=False):
+ raise EngineException("Method delete called directly", HTTPStatus.INTERNAL_SERVER_ERROR)
+
+ def edit(self, session, _id, indata=None, kwargs=None, force=False, content=None):
+ raise EngineException("Method edit called directly", HTTPStatus.INTERNAL_SERVER_ERROR)
diff --git a/osm_nbi/nbi.py b/osm_nbi/nbi.py
index e8f2246..1354f2c 100644
--- a/osm_nbi/nbi.py
+++ b/osm_nbi/nbi.py
@@ -675,9 +675,7 @@
force = kwargs.pop("FORCE")
else:
force = False
-
self._check_valid_url_method(method, main_topic, version, topic, _id, item, *args)
-
if main_topic == "admin" and topic == "tokens":
return self.token(method, _id, kwargs)
@@ -712,8 +710,7 @@
engine_topic = "vim_accounts"
if method == "GET":
- if item in ("nsd_content", "package_content", "artifacts", "vnfd", "nsd", "nst", "nst_content",
- "netslice_instances"):
+ if item in ("nsd_content", "package_content", "artifacts", "vnfd", "nsd", "nst", "nst_content"):
if item in ("vnfd", "nsd", "nst"):
path = "$DESCRIPTOR"
elif args:
@@ -759,14 +756,14 @@
outdata = {"id": _id}
cherrypy.response.status = HTTPStatus.ACCEPTED.value
elif topic == "netslice_instances_content":
- # creates NSI
+ # creates NetSlice_Instance_record (NSIR)
_id = self.engine.new_item(rollback, session, engine_topic, indata, kwargs, force=force)
- # creates nsilcmop
+ self._set_location_header(main_topic, version, topic, _id)
indata["lcmOperationType"] = "instantiate"
indata["nsiInstanceId"] = _id
- self.engine.new_item(rollback, session, "nsilcmops", indata, None)
- self._set_location_header(main_topic, version, topic, _id)
+ self.engine.new_item(rollback, session, "nsilcmops", indata, kwargs)
outdata = {"id": _id}
+
elif topic == "netslice_instances" and item:
indata["lcmOperationType"] = item
indata["nsiInstanceId"] = _id
diff --git a/osm_nbi/tests/cirros_slice/cirros_slice.yaml b/osm_nbi/tests/cirros_slice/cirros_slice.yaml
index 3b5c963..6f66c27 100644
--- a/osm_nbi/tests/cirros_slice/cirros_slice.yaml
+++ b/osm_nbi/tests/cirros_slice/cirros_slice.yaml
@@ -1,21 +1,17 @@
nst:
nst:
- id: cirros_nst
- name: cirros_slice_template
+ name: cirros_netslice_template
SNSSAI-identifier:
- slice-service-type: eMBB
quality-of-service:
- id: 1
netslice-subnet:
- - id: cirros_nsd_nst
- name: cirros_ns
- short-name: cirros_ns
- vendor: OSM
+ - id: cirros_nsd
is-shared-nss: 'false'
- description: Slice for osm-3.0-three 2nd-hackfest nsd2vnfs package
- version: '1.0'
- nsd-ref: cirros_2vnf_nsd
+ description: Slice example for osm-5.0
+ nsd-ref: cirros_nsd
instantiation-parameters:
- - name: cirros_2vnf_nsd
- nsdId: cirros_2vnf_nsd
+ - nsName: cirros_nsd
+ nsdId: cirros_nsd
vimAccountId: openstack_18
\ No newline at end of file
diff --git a/osm_nbi/tests/clear-all.sh b/osm_nbi/tests/clear-all.sh
index 5ba9d4b..c670106 100755
--- a/osm_nbi/tests/clear-all.sh
+++ b/osm_nbi/tests/clear-all.sh
@@ -66,7 +66,7 @@
done
fi
-for item in vim_accounts sdns nsrs vnfrs nslcmops nsds vnfds projects nsts # vims
+for item in vim_accounts sdns nsrs vnfrs nslcmops nsds vnfds projects nsts nsis nsilcmops # vims
do
curl --insecure ${OSMNBI_URL}/test/db-clear/${item}
echo " ${item}"
diff --git a/osm_nbi/tests/test.py b/osm_nbi/tests/test.py
index bcdfadf..2fbc217 100755
--- a/osm_nbi/tests/test.py
+++ b/osm_nbi/tests/test.py
@@ -1343,7 +1343,7 @@
def run(self, engine, test_osm, manual_check, test_params=None):
# nst CREATE
engine.get_autorization()
- r = engine.test("NST", "Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml,
+ r = engine.test("NST1", "Onboard NST", "POST", "/nst/v1/netslice_templates_content", headers_yaml,
self.nst_filenames,
201, {"Location": "/nst/v1/netslice_templates_content", "Content-Type": "application/yaml"},
"yaml")
@@ -1351,13 +1351,13 @@
nst_id = location[location.rfind("/")+1:]
# nstd SHOW OSM format
- r = engine.test("NST", "Show NSTD OSM format", "GET",
- "/nst/v1/netslice_templates_content/{}".format(nst_id), headers_json, None,
+ r = engine.test("NST2", "Show NSTD OSM format", "GET",
+ "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
200, r_header_json, "json")
# nstd DELETE
- r = engine.test("NST", "Delete NSTD", "DELETE",
- "/nst/v1/netslice_templates_content/{}".format(nst_id), headers_json, None,
+ r = engine.test("NST3", "Delete NSTD", "DELETE",
+ "/nst/v1/netslice_templates/{}".format(nst_id), headers_json, None,
204, None, 0)
diff --git a/osm_nbi/validation.py b/osm_nbi/validation.py
index da3dd04..62d9d22 100644
--- a/osm_nbi/validation.py
+++ b/osm_nbi/validation.py
@@ -192,6 +192,7 @@
"properties": {
"lcmOperationType": string_schema,
"nsInstanceId": id_schema,
+ "netsliceInstanceId": id_schema,
"nsName": name_schema,
"nsDescription": {"oneOf": [description_schema, {"type": "null"}]},
"nsdId": id_schema,
@@ -559,6 +560,38 @@
"pdus": pdu_edit_schema,
}
+# NETSLICE SCHEMAS
+nsi_instantiate = {
+ "title": "netslice action instantiate input schema",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "type": "object",
+ "properties": {
+ "lcmOperationType": string_schema,
+ "nsiInstanceId": id_schema,
+ "nsiName": name_schema,
+ "nsiDescription": {"oneOf": [description_schema, {"type": "null"}]},
+ "nstdId": string_schema,
+ "vimAccountId": id_schema,
+ "ssh_keys": {"type": "string"},
+ "nsi_id": id_schema,
+ "ns": {
+ "type": "array",
+ "minItems": 1,
+ "items": ns_instantiate
+ },
+ },
+ "required": ["nsiName", "nstdId", "vimAccountId"],
+ "additionalProperties": False
+}
+
+nsi_action = {
+
+}
+
+nsi_terminate = {
+
+}
+
class ValidationError(Exception):
pass