2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 # Copyright (c) 2019, CMCC Technologies Co., Ltd.
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
11 # http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.so.bpmn.infrastructure.scripts
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
46 import javax.ws.rs.NotFoundException
47 import javax.ws.rs.core.Response
49 import static org.apache.commons.lang3.StringUtils.isBlank
51 class DoCreateSliceServiceOption extends AbstractServiceTaskProcessor{
53 private static final Logger logger = LoggerFactory.getLogger( DoCreateSliceServiceOption.class)
55 ExceptionUtil exceptionUtil = new ExceptionUtil()
57 JsonUtils jsonUtil = new JsonUtils()
59 OofUtils oofUtils = new OofUtils()
61 ObjectMapper objectMapper = new ObjectMapper()
63 void preProcessRequest (DelegateExecution execution) {
67 void getNSIOptionfromOOF(DelegateExecution execution) {
69 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
70 logger.debug( "get NSI option OOF Url: " + urlString)
72 boolean isNSISuggested = true
73 execution.setVariable("isNSISuggested",isNSISuggested)
75 //Prepare auth for OOF - Begin
77 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
78 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
80 String basicAuthValue = utils.encrypt(basicAuth, msokey)
81 if (basicAuthValue != null) {
82 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
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")
92 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
93 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
96 //Prepare auth for OOF - End
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}"
108 String oofRequest = oofUtils.buildSelectNSIRequest(requestId, nstInfo, profileInfo)
109 logger.debug("Sending request to OOF: " + oofRequest)
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)
117 processOOFResponse(httpResponse, execution)
120 logger.debug("start parseServiceProfile")
121 parseServiceProfile(execution)
122 logger.debug("end parseServiceProfile")
125 private void processOOFResponse(Response httpResponse, DelegateExecution execution) {
126 int responseCode = httpResponse.getStatus()
127 logger.debug("OOF sync response code is: " + responseCode)
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")
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)
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")
144 String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
145 Boolean isSharable = resourceSharingLevel.equals("shared")
147 if (solutions != null) {
150 processSharedNSISolutions(solutions, execution)
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>
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()
166 sliceTaskParams.setAnSuggestNssiId(nssiId)
167 sliceTaskParams.setAnSuggestNssiName(nssiName)
170 sliceTaskParams.setCnSuggestNssiId(nssiId)
171 sliceTaskParams.setCnSuggestNssiName(nssiName)
174 sliceTaskParams.setTnSuggestNssiId(nssiId)
175 sliceTaskParams.setTnSuggestNssiName(nssiName)
185 execution.setVariable("sliceTaskParams", sliceTaskParams)
186 logger.debug("sliceTaskParams: "+sliceTaskParams.convertToJson())
188 logger.debug("*** Completed options Call to OOF ***")
191 private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
192 if (!solutions.containsKey("sharedNSISolutions"))
194 logger.error("OOF don't return sharedNSISolutions")
197 String nsiName, nsiInstanceId, nssiId, nssiName
199 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
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)
207 //Temporary modification
208 List NSSIs = sharedNSIsolution.get("NSSIs")
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)
220 logger.debug("OOF sharedNSISolution nsiInstanceId:${nsiInstanceId}, nsiName:${nsiName}, nssiId:${nssiId}, nssiName:${nssiName}")
221 logger.debug("OOF SliceProfile:"+sliceProfile.toString())
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)
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)
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)
251 logger.debug("Finish parseServiceProfile")
254 Map getSliceProfile(String serviceType, String domain, Map<String, Object> serviceProfile) {
256 Integer domainLatency = (Integer) serviceProfile.get("latency")/3
260 profileMapStr = """ {
261 "latency": ${domainLatency},
263 "uEMobilityLevel": "uEMobilityLevel",
264 "coverageAreaTAList": "coverageAreaTAList",
267 """.trim().replaceAll(" ", "")
271 "latency":${domainLatency},
273 "e2eLatency":"latency",
276 """.trim().replaceAll(" ", "")
279 profileMapStr = """ {
280 "areaTrafficCapDL":"areaTrafficCapDL",
281 "maxNumberofUEs":"maxNumberofUEs",
282 "latency":${domainLatency},
283 "expDataRateUL":"expDataRateUL",
285 "areaTrafficCapUL":"areaTrafficCapUL",
286 "uEMobilityLevel":"uEMobilityLevel",
287 "expDataRateDL":"expDataRateDL",
288 "activityFactor":"activityFactor",
289 "resourceSharingLevel":"resourceSharingLevel"
291 """.trim().replaceAll(" ", "")
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))
307 sliceProfile.put(key, profileMaps.get(key))
314 void processDecomposition(DelegateExecution execution){
315 logger.debug("Start processDecomposition")
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)
324 logger.debug("End processDecomposition")
328 void prepareNSTDecompose(DelegateExecution execution) {
330 String modelUuid = execution.getVariable("nstModelUuid")
331 String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
333 String serviceModelInfo = """{
334 "modelInvariantUuid":"${modelInvariantUuid}",
335 "modelUuid":"${modelUuid}",
338 execution.setVariable("serviceModelInfo", serviceModelInfo)
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}",
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)
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)
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()")
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 =""
398 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
399 logger.debug( "get NSI option OOF Url: " + urlString)
400 boolean isNSISuggested = false
401 execution.setVariable("isNSISuggested",isNSISuggested)
403 //Prepare auth for OOF - Begin
405 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
406 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
408 String basicAuthValue = utils.encrypt(basicAuth, msokey)
409 if (basicAuthValue != null) {
410 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
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")
420 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
421 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
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}"
434 String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
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)
442 int responseCode = httpResponse.getStatus()
443 logger.debug("OOF sync response code is: " + responseCode)
445 if(responseCode != 200){
446 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
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)
457 if(isBlank(nssiInstanceId)){
458 logger.debug( "There is no valid NSST suggested by OOF.")
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()
468 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
471 sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
472 sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
475 sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
476 sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
479 sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
480 sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
485 }catch(NotFoundException e)
487 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
490 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
493 logger.debug("Prepare NSSI option completed ")