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