9b78afba0378a85f2ce21fa4dae0e3035127ebdf
[so.git] /
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 prepareSelectNSIRequest(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         String requestId = execution.getVariable("msoRequestId")
75                 String messageType = "NSISelectionResponse"
76                 
77         Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
78         Map<String, Object> nstSolution = execution.getVariable("nstSolution")
79         logger.debug("Get NST selection from OOF: " + nstSolution.toString())
80         String nstInfo = """{
81             "modelInvariantId":"${nstSolution.invariantUUID}",
82             "modelVersionId":"${nstSolution.UUID}",
83             "modelName":"${nstSolution.NSTName}"
84          }"""
85                 
86                  execution.setVariable("nsiSelectionUrl", "/api/oof/selection/nsi/v1")
87                  execution.setVariable("nsiSelection_messageType",messageType)
88                  execution.setVariable("nsiSelection_correlator",requestId)
89                  String timeout = UrnPropertiesReader.getVariable("mso.adapters.oof.timeout", execution);
90                  execution.setVariable("nsiSelection_timeout",timeout)
91                  String oofRequest = oofUtils.buildSelectNSIRequest(requestId, nstInfo,messageType, profileInfo)
92                  execution.setVariable("nsiSelection_oofRequest",oofRequest)
93                  logger.debug("Sending request to OOF: " + oofRequest)
94     }
95
96     void processOOFResponse(Response httpResponse, DelegateExecution execution) {
97         int responseCode = httpResponse.getStatus()
98         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
99             String OOFResponse = execution.getVariable("nsiSelection_oofResponse")
100             logger.debug("NSI OOFResponse is: " + OOFResponse)
101             execution.setVariable("OOFResponse", OOFResponse)
102             //This needs to be changed to derive a value when we add policy to decide the solution options.
103             Map OOFResponseObject = new JsonSlurper().parseText(OOFResponse)
104             Map solutions = OOFResponseObject.get("solutions")
105
106             String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
107             Boolean isSharable = resourceSharingLevel.equals("shared")
108
109             if (solutions != null) {
110                 if (isSharable && hasSharedNSIsolutions(solutions)) {
111                     //sharedNSISolution
112                     processSharedNSISolutions(solutions, execution)
113                 }
114                 else if(solutions.containsKey("newNSISolutions")) {
115                     processNewNSISolutions(solutions, execution)
116                 }
117             }
118             execution.setVariable("sliceTaskParams", sliceTaskParams)
119             logger.debug("sliceTaskParams: "+sliceTaskParams.convertToJson())
120         logger.debug("*** Completed options Call to OOF ***")
121                 //解析sliceProfile
122                 logger.debug("start parseServiceProfile")
123                 parseServiceProfile(execution)
124                 logger.debug("end parseServiceProfile")
125     }
126
127     private boolean hasSharedNSIsolutions( Map solutions){
128         if(solutions.containsKey("sharedNSISolutions")){
129             List sharedNSIsolutions = solutions.get("sharedNSISolutions")
130             if (sharedNSIsolutions != null && !sharedNSIsolutions.isEmpty()) {
131                 return  true
132             }
133         }
134         return false
135     }
136
137     private void processNewNSISolutions(Map solutions, DelegateExecution execution) {
138         int index = 0
139         List<Map> newNSISolutions = solutions.get("newNSISolutions")
140         List<Map> NSSImap = new ArrayList<>()
141         if (newNSISolutions != null && newNSISolutions.size() > 0) {
142             NSSImap = newNSISolutions.get(index).get("NSSISolutions") as List<Map>
143             for (Map nssi : NSSImap) {
144                 Map oofSliceProfile = nssi.get("sliceProfile")
145                 String domain = oofSliceProfile.getOrDefault("domainType","")
146                 logger.debug("OOF newNSISolutions SliceProfile: " +oofSliceProfile.toString()+",domain:${domain}")
147                 if(null != domain){
148                     //TODO
149 //                    def nssiSolution = nssi.get("NSSISolution") as Map<String, ?>
150 //                    String nssiName = nssiSolution.getOrDefault("NSSIName", "")
151 //                    String nssiId = nssiSolution.getOrDefault("NSSIId", "")
152 //                    saveNSSIId(nssi, sliceTaskParams)
153                     Map<String, Object> sliceProfile = getSliceProfile(domain, execution, oofSliceProfile)
154                     saveSliceProfile(execution, domain, sliceProfile)
155
156                 }
157             }
158         }
159     }
160
161     private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
162         String nsiName, nsiInstanceId, nssiId, nssiName
163         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
164
165         Map sharedNSIsolution = ((List) solutions.get("sharedNSISolutions"))?.get(0)
166         nsiInstanceId = sharedNSIsolution.getOrDefault("NSIId", "")
167         nsiName = sharedNSIsolution.getOrDefault("NSIName", "")
168         sliceTaskParams.setSuggestNsiId(nsiInstanceId)
169         sliceTaskParams.setSuggestNsiName(nsiName)
170
171         //Temporary modification
172         List NSSIs = sharedNSIsolution.get("NSSIs")
173         for(Map nssi : NSSIs){
174             Map oofSliceProfile = ((List)nssi.get("sliceProfile"))?.get(0)
175             String domain = oofSliceProfile.getOrDefault("domainType","")
176             nssiId = nssi.getOrDefault("NSSIId","")
177             nssiName = nssi.getOrDefault("NSSIName","")
178             saveNSSIId(domain, nssiId, nssiName,execution)
179             Map<String, Object> sliceProfile = getSliceProfile(domain, execution, oofSliceProfile)
180             saveSliceProfile(execution, domain, sliceProfile)
181             logger.debug("OOF sharedNSISolution SliceProfile:"+oofSliceProfile.toString()+",domain:${domain}")
182             logger.debug("OOF sharedNSISolution nsiInstanceId:${nsiInstanceId}, nsiName:${nsiName}, nssiId:${nssiId}, nssiName:${nssiName}")
183         }
184     }
185
186     private void parseServiceProfile(DelegateExecution execution) {
187         logger.debug("Start parseServiceProfile")
188         String serviceType = execution.getVariable("serviceType")
189         Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
190         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
191         // set sliceProfile for three domains
192         if(!sliceTaskParams.getSliceProfileAn()){
193             Map<String, Object> sliceProfileAn = getSliceProfile( "AN", execution,null)
194             saveSliceProfile(execution,"AN",sliceProfileAn)
195         }
196
197         if(!sliceTaskParams.getSliceProfileTn()){
198             Map<String, Object> sliceProfileTn = getSliceProfile( "TN", execution,null)
199             saveSliceProfile(execution,"TN",sliceProfileTn)
200         }
201
202         if(!sliceTaskParams.getSliceProfileCn()){
203             Map<String, Object> sliceProfileCn = getSliceProfile( "CN", execution,null, )
204            saveSliceProfile(execution,"CN",sliceProfileCn)
205         }
206
207         logger.debug("Finish parseServiceProfile")
208     }
209
210     private void saveSliceProfile(DelegateExecution execution, String domain, Map<String, Object> sliceProfile){
211         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
212         if(domain.equalsIgnoreCase("AN")){
213             execution.setVariable("sliceProfileAn", sliceProfile)
214             sliceTaskParams.setSliceProfileAn(sliceProfile)
215             logger.debug("sliceProfileAn: " + sliceProfile)
216         }
217         else if(domain.equalsIgnoreCase("TN")){
218             execution.setVariable("sliceProfileTn", sliceProfile)
219             sliceTaskParams.setSliceProfileTn(sliceProfile)
220             logger.debug("sliceProfileTn: " + sliceProfile)
221         }
222         else if(domain.equalsIgnoreCase("CN")){
223             execution.setVariable("sliceProfileCn", sliceProfile)
224             sliceTaskParams.setSliceProfileCn(sliceProfile)
225             logger.debug("sliceProfileCn: " + sliceProfile)
226         }
227     }
228
229     private void saveNSSIId(String domain, String nssiId, String nssiName, DelegateExecution execution) {
230         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
231         if(domain.equalsIgnoreCase("AN")){
232             sliceTaskParams.setAnSuggestNssiId(nssiId)
233             sliceTaskParams.setAnSuggestNssiName(nssiName)
234         }
235         else if(domain.equalsIgnoreCase("CN")){
236             sliceTaskParams.setCnSuggestNssiId(nssiId)
237             sliceTaskParams.setCnSuggestNssiName(nssiName)
238         }
239         else if(domain.equalsIgnoreCase("TN")){
240             sliceTaskParams.setTnSuggestNssiId(nssiId)
241             sliceTaskParams.setTnSuggestNssiName(nssiName)
242         }
243     }
244
245     private Map getSliceProfile(String domain, DelegateExecution execution, Map<String, Object> oofSliceProfile) {
246         String profileMapStr
247         Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
248         Integer domainLatency = (Integer) serviceProfile.get("latency")/3
249
250         if(domain.equalsIgnoreCase("AN")){
251             profileMapStr = """ {
252                     "latency": ${domainLatency}, 
253                     "sNSSAI": "sNSSAI", 
254                     "uEMobilityLevel": "uEMobilityLevel", 
255                     "coverageAreaTAList": "coverageAreaTAList", 
256                     "5QI": 100
257                 }"""
258         }
259         else if(domain.equalsIgnoreCase("TN")){
260             profileMapStr =""" {
261                     "latency":${domainLatency},
262                     "sNSSAI":"sNSSAI", 
263                     "e2eLatency":"latency", 
264                     "bandwidth": 100
265                 }"""
266         }
267         else if(domain.equalsIgnoreCase("CN")){
268             profileMapStr = """ {
269                     "areaTrafficCapDL":"areaTrafficCapDL",
270                     "maxNumberofUEs":"maxNumberofUEs",
271                     "latency":${domainLatency},
272                     "expDataRateUL":"expDataRateUL", 
273                     "sNSSAI":"sNSSAI", 
274                     "areaTrafficCapUL":"areaTrafficCapUL",
275                     "uEMobilityLevel":"uEMobilityLevel", 
276                     "expDataRateDL":"expDataRateDL",  
277                     "activityFactor":"activityFactor",
278                     "resourceSharingLevel":"resourceSharingLevel"
279                 }"""
280         }
281
282             logger.debug("Profile map for " + domain + " : " + profileMapStr)
283         Map<String, Object> profileMaps = objectMapper.readValue(profileMapStr.trim().replaceAll(" ", ""), new TypeReference<Map<String, String>>(){})
284         Map<String, Object> sliceProfile = [:]
285         for (Map.Entry<String, String> profileMap : profileMaps) {
286             String key = profileMap.key
287             String value = profileMaps.get(key)
288             if(null != oofSliceProfile && oofSliceProfile.keySet().contains(key)){
289                 sliceProfile.put(key, oofSliceProfile.get(key))
290                 logger.debug("Get from oof, key:${key}, value: ${oofSliceProfile.get(key)}")
291             }
292             else if(serviceProfile.keySet().contains(value)){
293                 sliceProfile.put(key, serviceProfile.get(value))
294             }
295             else{
296                 sliceProfile.put(key, profileMaps.get(key))
297             }
298         }
299         return sliceProfile
300     }
301
302     void processDecomposition(DelegateExecution execution){
303         logger.debug("Start processDecomposition")
304
305         ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
306         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
307         String nstName = serviceDecomposition.getModelInfo().getModelName()
308         String nstId = serviceDecomposition.getModelInfo().getModelUuid()
309         sliceTaskParams.setNstName(nstName)
310         sliceTaskParams.setNstId(nstId)
311
312         logger.debug("End processDecomposition")
313     }
314
315
316     void prepareNSTDecompose(DelegateExecution execution) {
317
318         String modelUuid = execution.getVariable("nstModelUuid")
319         String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
320
321         String serviceModelInfo = """{
322             "modelInvariantUuid":"${modelInvariantUuid}",
323             "modelUuid":"${modelUuid}",
324             "modelVersion":""
325              }"""
326         execution.setVariable("serviceModelInfo", serviceModelInfo)
327     }
328
329     void prepareNSSTDecompose(DelegateExecution execution) {
330         Boolean isMoreNSSTtoProcess = false
331         Integer maxNSST = execution.getVariable("maxNSST")
332         Integer currentNSST=execution.getVariable("currentNSST")
333         List<String> nsstModelUUIDList = new ArrayList<>()
334         nsstModelUUIDList = execution.getVariable("nsstModelUUIDList")
335         String modelUuid = nsstModelUUIDList.get(currentNSST)
336         String serviceModelInfo = """{
337             "modelInvariantUuid":"",
338             "modelUuid":"${modelUuid}",
339             "modelVersion":""
340              }"""
341         execution.setVariable("serviceModelInfo", serviceModelInfo)
342         currentNSST=currentNSST+1
343         if(currentNSST<maxNSST)
344             isMoreNSSTtoProcess=true
345         execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
346         execution.setVariable("maxNSST",maxNSST)
347         execution.setVariable("currentNSST",currentNSST)
348     }
349
350
351     void prepareNSSTlistfromNST(DelegateExecution execution) {
352         //Need to update this part from decomposition.
353         logger.trace("Enter prepareNSSTlistfromNST()")
354         Boolean isMoreNSSTtoProcess = false
355         ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
356         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
357         String nstName = serviceDecomposition.getModelInfo().getModelName()
358         sliceTaskParams.setNstName(nstName)
359         String nstId = serviceDecomposition.getModelInfo().getModelUuid()
360         sliceTaskParams.setNstId(nstId)
361         execution.setVariable("sliceTaskParams",sliceTaskParams)
362
363         List<ServiceProxy> proxyList = serviceDecomposition.getServiceProxy()
364         List<String> nsstModelUUIDList = new ArrayList<>()
365         for(ServiceProxy serviceProxy:proxyList)
366             nsstModelUUIDList.add(serviceProxy.getSourceModelUuid())
367         execution.setVariable("nsstModelUUIDList",nsstModelUUIDList)
368         Integer maxNSST = nsstModelUUIDList.size()
369         Integer currentNSST=0
370         execution.setVariable("maxNSST",maxNSST)
371         execution.setVariable("currentNSST",currentNSST)
372         if(currentNSST<maxNSST)
373             isMoreNSSTtoProcess=true
374         execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
375         logger.trace("Exit prepareNSSTlistfromNST()")
376
377     }
378
379     void getNSSTOption(DelegateExecution execution) {
380         ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
381         String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
382         String globalSubscriberId = execution.getVariable("globalSubscriberId")
383         String serviceType = execution.getVariable("subscriptionServiceType")
384         String nssiInstanceId =""
385         String nssiName =""
386         SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
387         logger.debug( "get NSI option OOF Url: " + urlString)
388         boolean isNSISuggested = false
389         execution.setVariable("isNSISuggested",isNSISuggested)
390
391         //Prepare auth for OOF - Begin
392         def authHeader = ""
393         String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
394         String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
395
396         String basicAuthValue = utils.encrypt(basicAuth, msokey)
397         if (basicAuthValue != null) {
398             logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
399             try {
400                 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
401                 execution.setVariable("BasicAuthHeaderValue", authHeader)
402             } catch (Exception ex) {
403                 logger.debug( "Unable to encode username and password string: " + ex)
404                 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
405                         "encode username and password string")
406             }
407         } else {
408             logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
409             exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
410                     "value null")
411         }
412         //Prepare auth for OOF - End
413         //Prepare send request to OOF - Begin
414         String requestId = execution.getVariable("msoRequestId")
415         Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
416         String nsstModelInvariantUuid = serviceDecomposition.getModelInfo().getModelInvariantUuid()
417         String nsstModelUuid = serviceDecomposition.getModelInfo().getModelUuid()
418         String nsstInfo = """"NSSTInfo": {
419         "invariantUUID":"${nsstModelInvariantUuid}",
420         "UUID":"${nsstModelUuid}"
421          }"""
422         String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
423
424
425         URL url = new URL(urlString+"/api/oof/v1/selectnssi")
426         HttpClient httpClient = new HttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
427         httpClient.addAdditionalHeader("Authorization", authHeader)
428         Response httpResponse = httpClient.post(oofRequest)
429
430         int responseCode = httpResponse.getStatus()
431         logger.debug("OOF sync response code is: " + responseCode)
432
433         if(responseCode != 200){
434             exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
435         }
436
437         if(httpResponse.hasEntity()){
438             String OOFResponse = httpResponse.readEntity(String.class)
439             execution.setVariable("OOFResponse", OOFResponse)
440             nssiInstanceId = jsonUtil.getJsonValue(OOFResponse, "NSSIIInfo.NSSIID")
441             nssiName = jsonUtil.getJsonValue(OOFResponse, "NSSIInfo.NSSIName")
442             execution.setVariable("nssiInstanceId",nssiInstanceId)
443             execution.setVariable("nssiName",nssiName)
444         }
445         if(isBlank(nssiInstanceId)){
446             logger.debug( "There is no valid NSST suggested by OOF.")
447         }else
448         {
449             try {
450                 AAIResourcesClient resourceClient = new AAIResourcesClient()
451                 AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalSubscriberId, serviceType, nssiInstanceId)
452                 AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
453                 Optional<org.onap.aai.domain.yang.ServiceInstance> si = wrapper.asBean(org.onap.aai.domain.yang.ServiceInstance.class)
454                 org.onap.aai.domain.yang.ServiceInstance nssi = si.get()
455
456                 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
457                 switch (domain) {
458                     case "AN":
459                         sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
460                         sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
461                         break
462                     case "CN":
463                         sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
464                         sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
465                         break
466                     case "TN":
467                         sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
468                         sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
469                         break
470                     default:
471                         break
472                 }
473             }catch(NotFoundException e)
474             {
475                 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
476             }catch(Exception e)
477             {
478                 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
479             }
480         }
481         logger.debug("Prepare NSSI option completed ")
482     }
483 }