Change API layer for NSI selection 61/111261/1
authordhebeha <dhebeha.mj71@wipro.com>
Fri, 14 Aug 2020 06:15:20 +0000 (11:45 +0530)
committerdhebeha <dhebeha.mj71@wipro.com>
Fri, 14 Aug 2020 06:16:13 +0000 (11:46 +0530)
Issue-ID: OPTFRA-802
Signed-off-by: dhebeha <dhebeha.mj71@wipro.com>
Change-Id: Ia7e36da8d9a4d1f3f8e8eb00a61e6b0b29fbbbf6

apps/slice_selection/models/api/nsi_selection_request.py
apps/slice_selection/models/api/nsi_selection_response.py
osdfapp.py
test/apps/slice_selection/nsi_selection_invalid_request.json [new file with mode: 0644]
test/apps/slice_selection/nsi_selection_request.json [new file with mode: 0644]
test/test_api_validation.py

index b7f3fbd..943fa56 100644 (file)
@@ -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()
index a927efa..3c6d35b 100644 (file)
 #
 
 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)
index 1099e55..5f45d9a 100755 (executable)
@@ -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 (file)
index 0000000..3ecd1e3
--- /dev/null
@@ -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 (file)
index 0000000..9c4fcda
--- /dev/null
@@ -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"
+         }
+      }
+   ]
+}
index 73d03cd..50941e9 100644 (file)
@@ -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())