From 01cd5da39097c948e4fba94eb785b60452c70af3 Mon Sep 17 00:00:00 2001 From: dhebeha Date: Fri, 14 Aug 2020 11:45:20 +0530 Subject: Change API layer for NSI selection Issue-ID: OPTFRA-802 Signed-off-by: dhebeha Change-Id: Ia7e36da8d9a4d1f3f8e8eb00a61e6b0b29fbbbf6 --- .../models/api/nsi_selection_request.py | 30 ++++---- .../models/api/nsi_selection_response.py | 52 +++---------- osdfapp.py | 9 ++- .../nsi_selection_invalid_request.json | 80 ++++++++++++++++++++ .../slice_selection/nsi_selection_request.json | 85 ++++++++++++++++++++++ test/test_api_validation.py | 11 +++ 6 files changed, 211 insertions(+), 56 deletions(-) create mode 100644 test/apps/slice_selection/nsi_selection_invalid_request.json create mode 100644 test/apps/slice_selection/nsi_selection_request.json diff --git a/apps/slice_selection/models/api/nsi_selection_request.py b/apps/slice_selection/models/api/nsi_selection_request.py index b7f3fbd..943fa56 100644 --- a/apps/slice_selection/models/api/nsi_selection_request.py +++ b/apps/slice_selection/models/api/nsi_selection_request.py @@ -26,29 +26,31 @@ class RequestInfo(OSDFModel): transactionId = StringType(required=True) requestId = StringType(required=True) callbackUrl = URLType(required=True) - callbackHeader = DictType(BaseType) sourceId = StringType(required=True) + callbackHeader = DictType(BaseType) timeout = IntType() + numSolutions = IntType() + addtnlArgs = DictType(BaseType) -class NSTInfo(OSDFModel): - """Preferred candidate for a resource (sent as part of a request from client)""" - modelInvariantId = StringType(required=True) - modelVersionId = StringType(required=True) - modelName = StringType() - modelType = StringType() - modelVersion = StringType() - modelCustomizationName = StringType() +class NxTInfo(OSDFModel): + """Information about NST/NSST model""" + invariantUUID = StringType(required=True) + UUID = StringType(required=True) + name = StringType(required=True) -class ServiceInfo(OSDFModel): - serviceInstanceId = StringType(required=True) - serviceName = StringType(required=True) +class SubnetCapability(OSDFModel): + """Subnet capability of every subnet""" + domainType = StringType(required=True) + capabilityDetails = DictType(BaseType, required=True) class NSISelectionAPI(OSDFModel): """Request for nsi selection (specific to optimization and additional metadata""" requestInfo = ModelType(RequestInfo, required=True) - NSTInfoList = ListType(ModelType(NSTInfo), required=True) - serviceInfo = ModelType(ServiceInfo, required=True) + NSTInfo = ModelType(NxTInfo, required=True) + NSSTInfo = ListType(ModelType(NxTInfo), required=True) serviceProfile = DictType(BaseType, required=True) + subnetCapabilities = ListType(ModelType(SubnetCapability), required=True) + preferReuse = BooleanType() diff --git a/apps/slice_selection/models/api/nsi_selection_response.py b/apps/slice_selection/models/api/nsi_selection_response.py index a927efa..3c6d35b 100644 --- a/apps/slice_selection/models/api/nsi_selection_response.py +++ b/apps/slice_selection/models/api/nsi_selection_response.py @@ -17,66 +17,38 @@ # from osdf.models.api.common import OSDFModel -from schematics.types import BaseType, StringType +from schematics.types import BaseType, StringType, BooleanType from schematics.types.compound import ModelType, ListType, DictType # TODO: update osdf.models -class NSSI(OSDFModel): - NSSIId = StringType(required=True) - NSSIName = StringType(required=True) - UUID = StringType(required=True) - invariantUUID = StringType(required=True) - sliceProfile = ListType(DictType(BaseType)) - - class SharedNSISolution(OSDFModel): + """Represents the shared NSI Solution object""" invariantUUID = StringType(required=True) UUID = StringType(required=True) NSIName = StringType(required=True) NSIId = StringType(required=True) matchLevel = StringType(required=True) - NSSIs = ListType(ModelType(NSSI)) - - -class NSSTInfo(OSDFModel): - invariantUUID = StringType(required=True) - UUID = StringType(required=True) - NSSTName = StringType(required=True) - - -class NSSIInfo(OSDFModel): - NSSIName = StringType(required=True) - NSSIId = StringType(required=True) - matchLevel = StringType(required=True) - - -class NSSISolution(OSDFModel): - sliceProfile = DictType(BaseType) - NSSTInfo = ModelType(NSSTInfo, required=True) - NSSISolution = ModelType(NSSIInfo, required=True) - - -class NSTInfo(OSDFModel): - invariantUUID = StringType(required=True) - UUID = StringType(required=True) - NSTName = StringType(required=True) class NewNSISolution(OSDFModel): + """Represents the New NSI Solution object containing tuple of slice profiles""" + sliceProfiles = ListType(DictType(BaseType), required=True) matchLevel = StringType(required=True) - NSTInfo = ModelType(NSTInfo, required=True) - NSSISolutions = ListType(ModelType(NSSISolution)) -class Solution(OSDFModel): - sharedNSISolutions = ListType(ModelType(SharedNSISolution)) - newNSISolutions = ListType(ModelType(NewNSISolution)) +class NSISolution(OSDFModel): + """Represents the NSI Solution object""" + """This solution object contains either sharedNSISolution or newNSISolution""" + existingNSI = BooleanType(required=True) + sharedNSISolution = ModelType(SharedNSISolution) + newNSISolution = ModelType(NewNSISolution) class NSISelectionResponse(OSDFModel): + """Response sent to NSMF(SO)""" transactionId = StringType(required=True) requestId = StringType(required=True) requestStatus = StringType(required=True) + solutions = ListType(ModelType(NSISolution), required=True) statusMessage = StringType() - solutions = ModelType(Solution, required=True) diff --git a/osdfapp.py b/osdfapp.py index 1099e55..5f45d9a 100755 --- a/osdfapp.py +++ b/osdfapp.py @@ -123,7 +123,7 @@ def do_pci_optimization(): req_id = request_json['requestInfo']['requestId'] audit_log.info('requestID obtained==>') audit_log.info(req_id) - + g.request_id = req_id audit_log.info(MH.received_request(request.url, request.remote_addr, json.dumps(request_json))) PCIOptimizationAPI(request_json).validate() @@ -146,7 +146,12 @@ def do_nsi_selection(): g.request_id = req_id audit_log.info(MH.received_request(request.url, request.remote_addr, json.dumps(request_json))) NSISelectionAPI(request_json).validate() - return process_nsi_selection_opt(request_json, osdf_config) + audit_log.info(MH.new_worker_thread(req_id, "[for NSI selection]")) + t = Thread(target=process_nsi_selection_opt, args=(request_json, osdf_config)) + t.start() + return req_accept(request_id=req_id, + transaction_id=request_json['requestInfo']['transactionId'], + request_status="accepted", status_message="") if __name__ == "__main__": diff --git a/test/apps/slice_selection/nsi_selection_invalid_request.json b/test/apps/slice_selection/nsi_selection_invalid_request.json new file mode 100644 index 0000000..3ecd1e3 --- /dev/null +++ b/test/apps/slice_selection/nsi_selection_invalid_request.json @@ -0,0 +1,80 @@ +{ + "serviceProfile": { + "latency": 2, + "security": "High", + "reliability": 99.9999, + "trafficDensity": 1, + "connDensity": 100000, + "expDataRate": 50, + "jitter": 1, + "survivalTime": 0, + "resourceSharingLevel":"shared" + }, + "requestInfo": { + "transactionId": "d290f1ee-6c54-4b01-90e6-d701748f0851", + "requestId": "d290f1ee-6c54-4b01-90e6-d701748f0851", + "callbackUrl": "http://0.0.0.0:9000/osdfCallback/", + "sourceId": "SO", + "timeout": 5 + }, + "NSSTInfo":[ + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa2", + "invariantUUID":"2fa85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-an-nf" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa3", + "invariantUUID":"4fa85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-cn" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa4", + "invariantUUID":"5ta85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-tn-fh" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa5", + "invariantUUID":"6ya85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-tn-mh" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa7", + "invariantUUID":"7ua85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-tn-bh" + } + ], + "preferReuse":true, + "subnetCapabilities":[ + { + "domainType":"AN-NF", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"CN", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"TN-FH", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"TN-MH", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"TN-BH", + "capabilityDetails":{ + "blob":"content" + } + } + ] +} diff --git a/test/apps/slice_selection/nsi_selection_request.json b/test/apps/slice_selection/nsi_selection_request.json new file mode 100644 index 0000000..9c4fcda --- /dev/null +++ b/test/apps/slice_selection/nsi_selection_request.json @@ -0,0 +1,85 @@ +{ + "serviceProfile": { + "latency": 2, + "security": "High", + "reliability": 99.9999, + "trafficDensity": 1, + "connDensity": 100000, + "expDataRate": 50, + "jitter": 1, + "survivalTime": 0, + "resourceSharingLevel":"shared" + }, + "requestInfo": { + "transactionId": "d290f1ee-6c54-4b01-90e6-d701748f0851", + "requestId": "d290f1ee-6c54-4b01-90e6-d701748f0851", + "callbackUrl": "http://0.0.0.0:9000/osdfCallback/", + "sourceId": "SO", + "timeout": 5 + }, + "NSTInfo":{ + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa1", + "invariantUUID":"7ua85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-nst" + }, + "NSSTInfo":[ + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa2", + "invariantUUID":"2fa85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-an-nf" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa3", + "invariantUUID":"4fa85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-cn" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa4", + "invariantUUID":"5ta85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-tn-fh" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa5", + "invariantUUID":"6ya85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-tn-mh" + }, + { + "UUID":"3fa85f64-5717-4562-b3fc-2c963f66afa7", + "invariantUUID":"7ua85f64-5717-4562-b3fc-2c963f66afa6", + "name":"embb-tn-bh" + } + ], + "preferReuse":true, + "subnetCapabilities":[ + { + "domainType":"AN-NF", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"CN", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"TN-FH", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"TN-MH", + "capabilityDetails":{ + "blob":"content" + } + }, + { + "domainType":"TN-BH", + "capabilityDetails":{ + "blob":"content" + } + } + ] +} diff --git a/test/test_api_validation.py b/test/test_api_validation.py index 73d03cd..50941e9 100644 --- a/test/test_api_validation.py +++ b/test/test_api_validation.py @@ -22,6 +22,7 @@ from schematics.exceptions import DataError from apps.placement.models.api.placementRequest import PlacementAPI from apps.placement.models.api.placementResponse import PlacementResponse +from apps.slice_selection.models.api.nsi_selection_request import NSISelectionAPI class TestReqValidation(unittest.TestCase): @@ -36,6 +37,16 @@ class TestReqValidation(unittest.TestCase): req_json = json.loads(open(req_file).read()) self.assertEqual(PlacementAPI(req_json).validate(), None) + def test_req_nsi_validation(self): + req_file = "./test/apps/slice_selection/nsi_selection_request.json" + req_json = json.loads(open(req_file).read()) + self.assertEqual(NSISelectionAPI(req_json).validate(), None) + + def test_req_invalid_nsi(self): + req_file = "./test/apps/slice_selection/nsi_selection_invalid_request.json" + req_json = json.loads(open(req_file).read()) + self.assertRaises(DataError, lambda: NSISelectionAPI(req_json).validate()) + def test_req_failure(self): req_json = {} self.assertRaises(DataError, lambda: PlacementAPI(req_json).validate()) -- cgit 1.2.3-korg