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)
139 //This needs to be changed to derive a value when we add policy to decide the solution options.
140 Map OOFResponseObject = new JsonSlurper().parseText(OOFResponse)
141 Map solutions = OOFResponseObject.get("solutions")
143 String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
144 Boolean isSharable = resourceSharingLevel.equals("shared")
146 if (solutions != null) {
147 if (isSharable && hasSharedNSIsolutions(solutions)) {
149 processSharedNSISolutions(solutions, execution)
151 else if(solutions.containsKey("newNSISolutions")) {
152 processNewNSISolutions(solutions, execution)
155 execution.setVariable("sliceTaskParams", sliceTaskParams)
156 logger.debug("sliceTaskParams: "+sliceTaskParams.convertToJson())
158 logger.debug("*** Completed options Call to OOF ***")
161 private boolean hasSharedNSIsolutions( Map solutions){
162 if(solutions.containsKey("sharedNSISolutions")){
163 List sharedNSIsolutions = solutions.get("sharedNSISolutions")
164 if (sharedNSIsolutions != null && !sharedNSIsolutions.isEmpty()) {
171 private void processNewNSISolutions(Map solutions, DelegateExecution execution) {
173 List<Map> newNSISolutions = solutions.get("newNSISolutions")
174 List<Map> NSSImap = new ArrayList<>()
175 if (newNSISolutions != null && newNSISolutions.size() > 0) {
176 NSSImap = newNSISolutions.get(index).get("NSSISolutions") as List<Map>
177 for (Map nssi : NSSImap) {
178 Map oofSliceProfile = nssi.get("sliceProfile")
179 String domain = oofSliceProfile.getOrDefault("domainType","")
180 logger.debug("OOF newNSISolutions SliceProfile: " +oofSliceProfile.toString()+",domain:${domain}")
183 // def nssiSolution = nssi.get("NSSISolution") as Map<String, ?>
184 // String nssiName = nssiSolution.getOrDefault("NSSIName", "")
185 // String nssiId = nssiSolution.getOrDefault("NSSIId", "")
186 // saveNSSIId(nssi, sliceTaskParams)
187 Map<String, Object> sliceProfile = getSliceProfile(domain, execution, oofSliceProfile)
188 saveSliceProfile(execution, domain, sliceProfile)
195 private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
196 String nsiName, nsiInstanceId, nssiId, nssiName
197 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
199 Map sharedNSIsolution = ((List) solutions.get("sharedNSISolutions"))?.get(0)
200 nsiInstanceId = sharedNSIsolution.getOrDefault("NSIId", "")
201 nsiName = sharedNSIsolution.getOrDefault("NSIName", "")
202 sliceTaskParams.setSuggestNsiId(nsiInstanceId)
203 sliceTaskParams.setSuggestNsiName(nsiName)
205 //Temporary modification
206 List NSSIs = sharedNSIsolution.get("NSSIs")
207 for(Map nssi : NSSIs){
208 Map oofSliceProfile = ((List)nssi.get("sliceProfile"))?.get(0)
209 String domain = oofSliceProfile.getOrDefault("domainType","")
210 nssiId = nssi.getOrDefault("NSSIId","")
211 nssiName = nssi.getOrDefault("NSSIName","")
212 saveNSSIId(domain, nssiId, nssiName,execution)
213 Map<String, Object> sliceProfile = getSliceProfile(domain, execution, oofSliceProfile)
214 saveSliceProfile(execution, domain, sliceProfile)
215 logger.debug("OOF sharedNSISolution SliceProfile:"+oofSliceProfile.toString()+",domain:${domain}")
216 logger.debug("OOF sharedNSISolution nsiInstanceId:${nsiInstanceId}, nsiName:${nsiName}, nssiId:${nssiId}, nssiName:${nssiName}")
220 private void parseServiceProfile(DelegateExecution execution) {
221 logger.debug("Start parseServiceProfile")
222 String serviceType = execution.getVariable("serviceType")
223 Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
224 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
225 // set sliceProfile for three domains
226 if(!sliceTaskParams.getSliceProfileAn()){
227 Map<String, Object> sliceProfileAn = getSliceProfile( "AN", execution,null)
228 saveSliceProfile(execution,"AN",sliceProfileAn)
231 if(!sliceTaskParams.getSliceProfileTn()){
232 Map<String, Object> sliceProfileTn = getSliceProfile( "TN", execution,null)
233 saveSliceProfile(execution,"TN",sliceProfileTn)
236 if(!sliceTaskParams.getSliceProfileCn()){
237 Map<String, Object> sliceProfileCn = getSliceProfile( "CN", execution,null, )
238 saveSliceProfile(execution,"CN",sliceProfileCn)
241 logger.debug("Finish parseServiceProfile")
244 private void saveSliceProfile(DelegateExecution execution, String domain, Map<String, Object> sliceProfile){
245 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
246 if(domain.equalsIgnoreCase("AN")){
247 execution.setVariable("sliceProfileAn", sliceProfile)
248 sliceTaskParams.setSliceProfileAn(sliceProfile)
249 logger.debug("sliceProfileAn: " + sliceProfile)
251 else if(domain.equalsIgnoreCase("TN")){
252 execution.setVariable("sliceProfileTn", sliceProfile)
253 sliceTaskParams.setSliceProfileTn(sliceProfile)
254 logger.debug("sliceProfileTn: " + sliceProfile)
256 else if(domain.equalsIgnoreCase("CN")){
257 execution.setVariable("sliceProfileCn", sliceProfile)
258 sliceTaskParams.setSliceProfileCn(sliceProfile)
259 logger.debug("sliceProfileCn: " + sliceProfile)
263 private void saveNSSIId(String domain, String nssiId, String nssiName, DelegateExecution execution) {
264 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
265 if(domain.equalsIgnoreCase("AN")){
266 sliceTaskParams.setAnSuggestNssiId(nssiId)
267 sliceTaskParams.setAnSuggestNssiName(nssiName)
269 else if(domain.equalsIgnoreCase("CN")){
270 sliceTaskParams.setCnSuggestNssiId(nssiId)
271 sliceTaskParams.setCnSuggestNssiName(nssiName)
273 else if(domain.equalsIgnoreCase("TN")){
274 sliceTaskParams.setTnSuggestNssiId(nssiId)
275 sliceTaskParams.setTnSuggestNssiName(nssiName)
279 private Map getSliceProfile(String domain, DelegateExecution execution, Map<String, Object> oofSliceProfile) {
281 Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
282 Integer domainLatency = (Integer) serviceProfile.get("latency")/3
284 if(domain.equalsIgnoreCase("AN")){
285 profileMapStr = """ {
286 "latency": ${domainLatency},
288 "uEMobilityLevel": "uEMobilityLevel",
289 "coverageAreaTAList": "coverageAreaTAList",
293 else if(domain.equalsIgnoreCase("TN")){
295 "latency":${domainLatency},
297 "e2eLatency":"latency",
301 else if(domain.equalsIgnoreCase("CN")){
302 profileMapStr = """ {
303 "areaTrafficCapDL":"areaTrafficCapDL",
304 "maxNumberofUEs":"maxNumberofUEs",
305 "latency":${domainLatency},
306 "expDataRateUL":"expDataRateUL",
308 "areaTrafficCapUL":"areaTrafficCapUL",
309 "uEMobilityLevel":"uEMobilityLevel",
310 "expDataRateDL":"expDataRateDL",
311 "activityFactor":"activityFactor",
312 "resourceSharingLevel":"resourceSharingLevel"
316 logger.debug("Profile map for " + domain + " : " + profileMapStr)
317 Map<String, Object> profileMaps = objectMapper.readValue(profileMapStr.trim().replaceAll(" ", ""), new TypeReference<Map<String, String>>(){})
318 Map<String, Object> sliceProfile = [:]
319 for (Map.Entry<String, String> profileMap : profileMaps) {
320 String key = profileMap.key
321 String value = profileMaps.get(key)
322 if(null != oofSliceProfile && oofSliceProfile.keySet().contains(key)){
323 sliceProfile.put(key, oofSliceProfile.get(key))
324 logger.debug("Get from oof, key:${key}, value: ${oofSliceProfile.get(key)}")
326 else if(serviceProfile.keySet().contains(value)){
327 sliceProfile.put(key, serviceProfile.get(value))
330 sliceProfile.put(key, profileMaps.get(key))
336 void processDecomposition(DelegateExecution execution){
337 logger.debug("Start processDecomposition")
339 ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
340 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
341 String nstName = serviceDecomposition.getModelInfo().getModelName()
342 String nstId = serviceDecomposition.getModelInfo().getModelUuid()
343 sliceTaskParams.setNstName(nstName)
344 sliceTaskParams.setNstId(nstId)
346 logger.debug("End processDecomposition")
350 void prepareNSTDecompose(DelegateExecution execution) {
352 String modelUuid = execution.getVariable("nstModelUuid")
353 String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
355 String serviceModelInfo = """{
356 "modelInvariantUuid":"${modelInvariantUuid}",
357 "modelUuid":"${modelUuid}",
360 execution.setVariable("serviceModelInfo", serviceModelInfo)
363 void prepareNSSTDecompose(DelegateExecution execution) {
364 Boolean isMoreNSSTtoProcess = false
365 Integer maxNSST = execution.getVariable("maxNSST")
366 Integer currentNSST=execution.getVariable("currentNSST")
367 List<String> nsstModelUUIDList = new ArrayList<>()
368 nsstModelUUIDList = execution.getVariable("nsstModelUUIDList")
369 String modelUuid = nsstModelUUIDList.get(currentNSST)
370 String serviceModelInfo = """{
371 "modelInvariantUuid":"",
372 "modelUuid":"${modelUuid}",
375 execution.setVariable("serviceModelInfo", serviceModelInfo)
376 currentNSST=currentNSST+1
377 if(currentNSST<maxNSST)
378 isMoreNSSTtoProcess=true
379 execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
380 execution.setVariable("maxNSST",maxNSST)
381 execution.setVariable("currentNSST",currentNSST)
385 void prepareNSSTlistfromNST(DelegateExecution execution) {
386 //Need to update this part from decomposition.
387 logger.trace("Enter prepareNSSTlistfromNST()")
388 Boolean isMoreNSSTtoProcess = false
389 ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
390 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
391 String nstName = serviceDecomposition.getModelInfo().getModelName()
392 sliceTaskParams.setNstName(nstName)
393 String nstId = serviceDecomposition.getModelInfo().getModelUuid()
394 sliceTaskParams.setNstId(nstId)
395 execution.setVariable("sliceTaskParams",sliceTaskParams)
397 List<ServiceProxy> proxyList = serviceDecomposition.getServiceProxy()
398 List<String> nsstModelUUIDList = new ArrayList<>()
399 for(ServiceProxy serviceProxy:proxyList)
400 nsstModelUUIDList.add(serviceProxy.getSourceModelUuid())
401 execution.setVariable("nsstModelUUIDList",nsstModelUUIDList)
402 Integer maxNSST = nsstModelUUIDList.size()
403 Integer currentNSST=0
404 execution.setVariable("maxNSST",maxNSST)
405 execution.setVariable("currentNSST",currentNSST)
406 if(currentNSST<maxNSST)
407 isMoreNSSTtoProcess=true
408 execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
409 logger.trace("Exit prepareNSSTlistfromNST()")
413 void getNSSTOption(DelegateExecution execution) {
414 ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
415 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
416 String globalSubscriberId = execution.getVariable("globalSubscriberId")
417 String serviceType = execution.getVariable("subscriptionServiceType")
418 String nssiInstanceId =""
420 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
421 logger.debug( "get NSI option OOF Url: " + urlString)
422 boolean isNSISuggested = false
423 execution.setVariable("isNSISuggested",isNSISuggested)
425 //Prepare auth for OOF - Begin
427 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
428 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
430 String basicAuthValue = utils.encrypt(basicAuth, msokey)
431 if (basicAuthValue != null) {
432 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
434 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
435 execution.setVariable("BasicAuthHeaderValue", authHeader)
436 } catch (Exception ex) {
437 logger.debug( "Unable to encode username and password string: " + ex)
438 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
439 "encode username and password string")
442 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
443 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
446 //Prepare auth for OOF - End
447 //Prepare send request to OOF - Begin
448 String requestId = execution.getVariable("msoRequestId")
449 Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
450 String nsstModelInvariantUuid = serviceDecomposition.getModelInfo().getModelInvariantUuid()
451 String nsstModelUuid = serviceDecomposition.getModelInfo().getModelUuid()
452 String nsstInfo = """"NSSTInfo": {
453 "invariantUUID":"${nsstModelInvariantUuid}",
454 "UUID":"${nsstModelUuid}"
456 String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
459 URL url = new URL(urlString+"/api/oof/v1/selectnssi")
460 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
461 httpClient.addAdditionalHeader("Authorization", authHeader)
462 Response httpResponse = httpClient.post(oofRequest)
464 int responseCode = httpResponse.getStatus()
465 logger.debug("OOF sync response code is: " + responseCode)
467 if(responseCode != 200){
468 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
471 if(httpResponse.hasEntity()){
472 String OOFResponse = httpResponse.readEntity(String.class)
473 execution.setVariable("OOFResponse", OOFResponse)
474 nssiInstanceId = jsonUtil.getJsonValue(OOFResponse, "NSSIIInfo.NSSIID")
475 nssiName = jsonUtil.getJsonValue(OOFResponse, "NSSIInfo.NSSIName")
476 execution.setVariable("nssiInstanceId",nssiInstanceId)
477 execution.setVariable("nssiName",nssiName)
479 if(isBlank(nssiInstanceId)){
480 logger.debug( "There is no valid NSST suggested by OOF.")
484 AAIResourcesClient resourceClient = new AAIResourcesClient()
485 AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalSubscriberId, serviceType, nssiInstanceId)
486 AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
487 Optional<org.onap.aai.domain.yang.ServiceInstance> si = wrapper.asBean(org.onap.aai.domain.yang.ServiceInstance.class)
488 org.onap.aai.domain.yang.ServiceInstance nssi = si.get()
490 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
493 sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
494 sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
497 sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
498 sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
501 sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
502 sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
507 }catch(NotFoundException e)
509 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
512 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
515 logger.debug("Prepare NSSI option completed ")