Merge "put appropriate annotations"
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / DoCreateSliceServiceOption.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  # Copyright (c) 2019, CMCC Technologies Co., Ltd.
6  #
7  # Licensed under the Apache License, Version 2.0 (the "License")
8  # you may not use this file except in compliance with the License.
9  # You may obtain a copy of the License at
10  #
11  #       http://www.apache.org/licenses/LICENSE-2.0
12  #
13  # Unless required by applicable law or agreed to in writing, software
14  # distributed under the License is distributed on an "AS IS" BASIS,
15  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  # See the License for the specific language governing permissions and
17  # limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.bpmn.infrastructure.scripts
22
23 import com.fasterxml.jackson.core.type.TypeReference
24 import com.fasterxml.jackson.databind.ObjectMapper
25 import groovy.json.JsonSlurper
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.logging.filter.base.ONAPComponents
28 import org.onap.so.beans.nsmf.SliceTaskParams
29 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
30 import org.onap.so.bpmn.common.scripts.ExceptionUtil
31 import org.onap.so.bpmn.common.scripts.OofUtils
32 import org.onap.so.bpmn.core.UrnPropertiesReader
33 import org.onap.so.bpmn.core.domain.ServiceDecomposition
34 import org.onap.so.bpmn.core.domain.ServiceProxy
35 import org.onap.so.bpmn.core.json.JsonUtils
36 import org.onap.so.client.HttpClient
37 import org.onap.so.client.HttpClientFactory
38 import org.onap.aaiclient.client.aai.AAIObjectType
39 import org.onap.aaiclient.client.aai.AAIResourcesClient
40 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
41 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
42 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
43 import org.slf4j.Logger
44 import org.slf4j.LoggerFactory
45
46 import javax.ws.rs.NotFoundException
47 import javax.ws.rs.core.Response
48
49 import static org.apache.commons.lang3.StringUtils.isBlank
50
51 class DoCreateSliceServiceOption extends AbstractServiceTaskProcessor{
52
53     private static final Logger logger = LoggerFactory.getLogger( DoCreateSliceServiceOption.class)
54
55     ExceptionUtil exceptionUtil = new ExceptionUtil()
56
57     JsonUtils jsonUtil = new JsonUtils()
58
59     OofUtils oofUtils = new OofUtils()
60
61     ObjectMapper objectMapper = new ObjectMapper()
62
63     void preProcessRequest (DelegateExecution execution) {
64     }
65
66
67     void getNSIOptionfromOOF(DelegateExecution execution) {
68
69         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
70         logger.debug( "get NSI option OOF Url: " + urlString)
71
72         boolean isNSISuggested = true
73         execution.setVariable("isNSISuggested",isNSISuggested)
74
75         //Prepare auth for OOF - Begin
76         def authHeader = ""
77         String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
78         String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
79
80         String basicAuthValue = utils.encrypt(basicAuth, msokey)
81         if (basicAuthValue != null) {
82             logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
83             try {
84                 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
85                 execution.setVariable("BasicAuthHeaderValue", authHeader)
86             } catch (Exception ex) {
87                 logger.debug( "Unable to encode username and password string: " + ex)
88                 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
89                         "encode username and password string")
90             }
91         } else {
92             logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
93             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
94                     "value null")
95         }
96         //Prepare auth for OOF - End
97
98         String requestId = execution.getVariable("msoRequestId")
99         Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
100         Map<String, Object> nstSolution = execution.getVariable("nstSolution")
101         logger.debug("Get NST selection from OOF: " + nstSolution.toString())
102         String nstInfo = """{
103             "modelInvariantId":"${nstSolution.invariantUUID}",
104             "modelVersionId":"${nstSolution.UUID}",
105             "modelName":"${nstSolution.NSTName}"
106          }"""
107
108         String oofRequest = oofUtils.buildSelectNSIRequest(requestId, nstInfo, profileInfo)
109         logger.debug("Sending request to OOF: " + oofRequest)
110
111         //send request to get NSI option - Begin
112         URL url = new URL(urlString+"/api/oof/selection/nsi/v1")
113         HttpClient httpClient = new HttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
114         httpClient.addAdditionalHeader("Authorization", authHeader)
115         Response httpResponse = httpClient.post(oofRequest)
116
117         processOOFResponse(httpResponse, execution)
118
119         //解析sliceProfile
120         logger.debug("start parseServiceProfile")
121         parseServiceProfile(execution)
122         logger.debug("end parseServiceProfile")
123     }
124
125     private void processOOFResponse(Response httpResponse, DelegateExecution execution) {
126         int responseCode = httpResponse.getStatus()
127         logger.debug("OOF sync response code is: " + responseCode)
128
129         if (responseCode != 200) {
130             exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
131             logger.debug("Info: No NSI suggested by OOF")
132         }
133
134         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
135         if (httpResponse.hasEntity()) {
136             String OOFResponse = httpResponse.readEntity(String.class)
137             logger.debug("NSI OOFResponse is: " + OOFResponse)
138             execution.setVariable("OOFResponse", OOFResponse)
139             int index = 0
140             //This needs to be changed to derive a value when we add policy to decide the solution options.
141             Map OOFResponseObject = new JsonSlurper().parseText(OOFResponse)
142             Map solutions = OOFResponseObject.get("solutions")
143
144             String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
145             Boolean isSharable = resourceSharingLevel.equals("shared")
146
147             if (solutions != null) {
148                 if (isSharable) {
149                     //sharedNSISolution
150                     processSharedNSISolutions(solutions, execution)
151                 } else {
152                     //TODO test OOF
153                     if (solutions.containsKey("newNSISolutions")) {
154                         List<Map> newNSISolutions = solutions.get("newNSISolutions")
155                         List<Map> NSSImap = new ArrayList<>()
156                         if (newNSISolutions != null && newNSISolutions.size() > 0) {
157                             NSSImap = newNSISolutions.get(index).get("NSSISolutions") as List<Map>
158                         }
159                         for (Map nssi : NSSImap) {
160                             def nssiSolution = nssi.get("NSSISolution") as Map<String, ?>
161                             String nssiName = nssiSolution.getOrDefault("NSSIName", "")
162                             String nssiId = nssiSolution.getOrDefault("NSSIId", "")
163                             String domain = nssiSolution.getOrDefault("domainName", "").toString().toUpperCase()
164                             switch (domain) {
165                                 case "AN":
166                                     sliceTaskParams.setAnSuggestNssiId(nssiId)
167                                     sliceTaskParams.setAnSuggestNssiName(nssiName)
168                                     break
169                                 case "CN":
170                                     sliceTaskParams.setCnSuggestNssiId(nssiId)
171                                     sliceTaskParams.setCnSuggestNssiName(nssiName)
172                                     break
173                                 case "TN":
174                                     sliceTaskParams.setTnSuggestNssiId(nssiId)
175                                     sliceTaskParams.setTnSuggestNssiName(nssiName)
176                                     break
177                                 default:
178                                     break
179                             }
180                         }
181                         //TODO sliceProfile
182                     }
183                 }
184             }
185             execution.setVariable("sliceTaskParams", sliceTaskParams)
186             logger.debug("sliceTaskParams: "+sliceTaskParams.convertToJson())
187         }
188         logger.debug("*** Completed options Call to OOF ***")
189     }
190
191     private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
192         if (!solutions.containsKey("sharedNSISolutions"))
193         {
194             logger.error("OOF don't return sharedNSISolutions")
195             return
196         }
197         String nsiName, nsiInstanceId, nssiId, nssiName
198         Map sliceProfile
199         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
200
201         Map sharedNSIsolution = ((List) solutions.get("sharedNSISolutions")).get(0)
202         nsiInstanceId = sharedNSIsolution.getOrDefault("NSIId", "")
203         nsiName = sharedNSIsolution.getOrDefault("NSIName", "")
204         sliceTaskParams.setSuggestNsiId(nsiInstanceId)
205         sliceTaskParams.setSuggestNsiName(nsiName)
206
207         //Temporary modification
208         List NSSIs = sharedNSIsolution.get("NSSIs")
209         if(NSSIs.size()==1){
210             Map nssi = NSSIs.get(0)
211             nssiId = nssi.getOrDefault("NSSIId","")
212             nssiName = nssi.getOrDefault("NSSIName","")
213             sliceTaskParams.setCnSuggestNssiId(nssiId)
214             //TODO Need update after OOF return camel key and domainType
215             sliceProfile = ((List)nssi.get("sliceProfile"))?.get(0)
216             sliceTaskParams.setCnSuggestNssiName(nssiName)
217 //            execution.setVariable("sliceProfileCn", sliceProfile)
218 //            sliceTaskParams.setSliceProfileCn(sliceProfile)
219         }
220         logger.debug("OOF sharedNSISolution nsiInstanceId:${nsiInstanceId}, nsiName:${nsiName}, nssiId:${nssiId}, nssiName:${nssiName}")
221         logger.debug("OOF SliceProfile:"+sliceProfile.toString())
222     }
223
224     void parseServiceProfile(DelegateExecution execution) {
225         logger.debug("Start parseServiceProfile")
226         String serviceType = execution.getVariable("serviceType")
227         Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
228         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
229         // set sliceProfile for three domains
230         if(!sliceTaskParams.getSliceProfileAn()){
231             Map<String, Object> sliceProfileAn = getSliceProfile(serviceType, "AN", serviceProfile)
232             execution.setVariable("sliceProfileAn", sliceProfileAn)
233             sliceTaskParams.setSliceProfileAn(sliceProfileAn)
234             logger.debug("sliceProfileAn: " + sliceProfileAn)
235         }
236
237         if(!sliceTaskParams.getSliceProfileTn()){
238             Map<String, Object> sliceProfileTn = getSliceProfile(serviceType, "TN", serviceProfile)
239             execution.setVariable("sliceProfileTn", sliceProfileTn)
240             sliceTaskParams.setSliceProfileTn(sliceProfileTn)
241             logger.debug("sliceProfileTn: " + sliceProfileTn)
242         }
243
244         if(!sliceTaskParams.getSliceProfileCn()){
245             Map<String, Object> sliceProfileCn = getSliceProfile(serviceType, "CN", serviceProfile)
246             execution.setVariable("sliceProfileCn", sliceProfileCn)
247             sliceTaskParams.setSliceProfileCn(sliceProfileCn)
248             logger.debug("sliceProfileCn: " + sliceProfileCn)
249         }
250
251         logger.debug("Finish parseServiceProfile")
252     }
253
254      Map getSliceProfile(String serviceType, String domain, Map<String, Object> serviceProfile) {
255         String profileMapStr
256         Integer domainLatency = (Integer) serviceProfile.get("latency")/3
257
258          switch (domain) {
259              case "AN":
260                  profileMapStr = """ {
261                     "latency": ${domainLatency}, 
262                     "sNSSAI": "sNSSAI", 
263                     "uEMobilityLevel": "uEMobilityLevel", 
264                     "coverageAreaTAList": "coverageAreaTAList", 
265                     "5QI": 100
266                 }
267                 """.trim().replaceAll(" ", "")
268                  break
269              case "TN":
270                  profileMapStr =""" {
271                     "latency":${domainLatency},
272                     "sNSSAI":"sNSSAI", 
273                     "e2eLatency":"latency", 
274                     "bandwidth": 100
275                 }
276                 """.trim().replaceAll(" ", "")
277                  break
278              case "CN":
279                  profileMapStr = """ {
280                     "areaTrafficCapDL":"areaTrafficCapDL",
281                     "maxNumberofUEs":"maxNumberofUEs",
282                     "latency":${domainLatency},
283                     "expDataRateUL":"expDataRateUL", 
284                     "sNSSAI":"sNSSAI", 
285                     "areaTrafficCapUL":"areaTrafficCapUL",
286                     "uEMobilityLevel":"uEMobilityLevel", 
287                     "expDataRateDL":"expDataRateDL",  
288                     "activityFactor":"activityFactor",
289                     "resourceSharingLevel":"resourceSharingLevel"
290                 }
291                 """.trim().replaceAll(" ", "")
292                  break
293              default:
294                  break
295          }
296
297             logger.debug("Profile map for " + domain + " : " + profileMapStr)
298         Map<String, Object> profileMaps = objectMapper.readValue(profileMapStr, new TypeReference<Map<String, String>>(){})
299         Map<String, Object> sliceProfile = [:]
300         for (Map.Entry<String, String> profileMap : profileMaps) {
301             String key = profileMap.key
302             String value = profileMaps.get(key)
303             if(serviceProfile.keySet().contains(value)){
304                 sliceProfile.put(key, serviceProfile.get(value))
305             }
306             else{
307                 sliceProfile.put(key, profileMaps.get(key))
308             }
309         }
310
311         return sliceProfile
312     }
313
314     void processDecomposition(DelegateExecution execution){
315         logger.debug("Start processDecomposition")
316
317         ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
318         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
319         String nstName = serviceDecomposition.getModelInfo().getModelName()
320         String nstId = serviceDecomposition.getModelInfo().getModelUuid()
321         sliceTaskParams.setNstName(nstName)
322         sliceTaskParams.setNstId(nstId)
323
324         logger.debug("End processDecomposition")
325     }
326
327
328     void prepareNSTDecompose(DelegateExecution execution) {
329
330         String modelUuid = execution.getVariable("nstModelUuid")
331         String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
332
333         String serviceModelInfo = """{
334             "modelInvariantUuid":"${modelInvariantUuid}",
335             "modelUuid":"${modelUuid}",
336             "modelVersion":""
337              }"""
338         execution.setVariable("serviceModelInfo", serviceModelInfo)
339     }
340
341     void prepareNSSTDecompose(DelegateExecution execution) {
342         Boolean isMoreNSSTtoProcess = false
343         Integer maxNSST = execution.getVariable("maxNSST")
344         Integer currentNSST=execution.getVariable("currentNSST")
345         List<String> nsstModelUUIDList = new ArrayList<>()
346         nsstModelUUIDList = execution.getVariable("nsstModelUUIDList")
347         String modelUuid = nsstModelUUIDList.get(currentNSST)
348         String serviceModelInfo = """{
349             "modelInvariantUuid":"",
350             "modelUuid":"${modelUuid}",
351             "modelVersion":""
352              }"""
353         execution.setVariable("serviceModelInfo", serviceModelInfo)
354         currentNSST=currentNSST+1
355         if(currentNSST<maxNSST)
356             isMoreNSSTtoProcess=true
357         execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
358         execution.setVariable("maxNSST",maxNSST)
359         execution.setVariable("currentNSST",currentNSST)
360     }
361
362
363     void prepareNSSTlistfromNST(DelegateExecution execution) {
364         //Need to update this part from decomposition.
365         logger.trace("Enter prepareNSSTlistfromNST()")
366         Boolean isMoreNSSTtoProcess = false
367         ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
368         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
369         String nstName = serviceDecomposition.getModelInfo().getModelName()
370         sliceTaskParams.setNstName(nstName)
371         String nstId = serviceDecomposition.getModelInfo().getModelUuid()
372         sliceTaskParams.setNstId(nstId)
373         execution.setVariable("sliceTaskParams",sliceTaskParams)
374
375         List<ServiceProxy> proxyList = serviceDecomposition.getServiceProxy()
376         List<String> nsstModelUUIDList = new ArrayList<>()
377         for(ServiceProxy serviceProxy:proxyList)
378             nsstModelUUIDList.add(serviceProxy.getSourceModelUuid())
379         execution.setVariable("nsstModelUUIDList",nsstModelUUIDList)
380         Integer maxNSST = nsstModelUUIDList.size()
381         Integer currentNSST=0
382         execution.setVariable("maxNSST",maxNSST)
383         execution.setVariable("currentNSST",currentNSST)
384         if(currentNSST<maxNSST)
385             isMoreNSSTtoProcess=true
386         execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
387         logger.trace("Exit prepareNSSTlistfromNST()")
388
389     }
390
391     void getNSSTOption(DelegateExecution execution) {
392         ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
393         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
394         String globalSubscriberId = execution.getVariable("globalSubscriberId")
395         String serviceType = execution.getVariable("subscriptionServiceType")
396         String nssiInstanceId =""
397         String nssiName =""
398         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
399         logger.debug( "get NSI option OOF Url: " + urlString)
400         boolean isNSISuggested = false
401         execution.setVariable("isNSISuggested",isNSISuggested)
402
403         //Prepare auth for OOF - Begin
404         def authHeader = ""
405         String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
406         String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
407
408         String basicAuthValue = utils.encrypt(basicAuth, msokey)
409         if (basicAuthValue != null) {
410             logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
411             try {
412                 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
413                 execution.setVariable("BasicAuthHeaderValue", authHeader)
414             } catch (Exception ex) {
415                 logger.debug( "Unable to encode username and password string: " + ex)
416                 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
417                         "encode username and password string")
418             }
419         } else {
420             logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
421             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
422                     "value null")
423         }
424         //Prepare auth for OOF - End
425         //Prepare send request to OOF - Begin
426         String requestId = execution.getVariable("msoRequestId")
427         Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
428         String nsstModelInvariantUuid = serviceDecomposition.getModelInfo().getModelInvariantUuid()
429         String nsstModelUuid = serviceDecomposition.getModelInfo().getModelUuid()
430         String nsstInfo = """"NSSTInfo": {
431         "invariantUUID":"${nsstModelInvariantUuid}",
432         "UUID":"${nsstModelUuid}"
433          }"""
434         String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
435
436
437         URL url = new URL(urlString+"/api/oof/v1/selectnssi")
438         HttpClient httpClient = new HttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
439         httpClient.addAdditionalHeader("Authorization", authHeader)
440         Response httpResponse = httpClient.post(oofRequest)
441
442         int responseCode = httpResponse.getStatus()
443         logger.debug("OOF sync response code is: " + responseCode)
444
445         if(responseCode != 200){
446             exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
447         }
448
449         if(httpResponse.hasEntity()){
450             String OOFResponse = httpResponse.readEntity(String.class)
451             execution.setVariable("OOFResponse", OOFResponse)
452             nssiInstanceId = jsonUtil.getJsonValue(OOFResponse, "NSSIIInfo.NSSIID")
453             nssiName = jsonUtil.getJsonValue(OOFResponse, "NSSIInfo.NSSIName")
454             execution.setVariable("nssiInstanceId",nssiInstanceId)
455             execution.setVariable("nssiName",nssiName)
456         }
457         if(isBlank(nssiInstanceId)){
458             logger.debug( "There is no valid NSST suggested by OOF.")
459         }else
460         {
461             try {
462                 AAIResourcesClient resourceClient = new AAIResourcesClient()
463                 AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalSubscriberId, serviceType, nssiInstanceId)
464                 AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
465                 Optional<org.onap.aai.domain.yang.ServiceInstance> si = wrapper.asBean(org.onap.aai.domain.yang.ServiceInstance.class)
466                 org.onap.aai.domain.yang.ServiceInstance nssi = si.get()
467
468                 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
469                 switch (domain) {
470                     case "AN":
471                         sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
472                         sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
473                         break
474                     case "CN":
475                         sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
476                         sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
477                         break
478                     case "TN":
479                         sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
480                         sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
481                         break
482                     default:
483                         break
484                 }
485             }catch(NotFoundException e)
486             {
487                 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
488             }catch(Exception e)
489             {
490                 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
491             }
492         }
493         logger.debug("Prepare NSSI option completed ")
494     }
495 }