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 prepareSelectNSIRequest(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)
74 String requestId = execution.getVariable("msoRequestId")
75 String messageType = "NSISelectionResponse"
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())
81 "modelInvariantId":"${nstSolution.invariantUUID}",
82 "modelVersionId":"${nstSolution.UUID}",
83 "modelName":"${nstSolution.NSTName}"
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)
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")
106 String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
107 Boolean isSharable = resourceSharingLevel.equals("shared")
109 if (solutions != null) {
110 if (isSharable && hasSharedNSIsolutions(solutions)) {
112 processSharedNSISolutions(solutions, execution)
114 else if(solutions.containsKey("newNSISolutions")) {
115 processNewNSISolutions(solutions, execution)
118 execution.setVariable("sliceTaskParams", sliceTaskParams)
119 logger.debug("sliceTaskParams: "+sliceTaskParams.convertToJson())
120 logger.debug("*** Completed options Call to OOF ***")
122 logger.debug("start parseServiceProfile")
123 parseServiceProfile(execution)
124 logger.debug("end parseServiceProfile")
127 private boolean hasSharedNSIsolutions( Map solutions){
128 if(solutions.containsKey("sharedNSISolutions")){
129 List sharedNSIsolutions = solutions.get("sharedNSISolutions")
130 if (sharedNSIsolutions != null && !sharedNSIsolutions.isEmpty()) {
137 private void processNewNSISolutions(Map solutions, DelegateExecution execution) {
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}")
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)
161 private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
162 String nsiName, nsiInstanceId, nssiId, nssiName
163 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
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)
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}")
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)
197 if(!sliceTaskParams.getSliceProfileTn()){
198 Map<String, Object> sliceProfileTn = getSliceProfile( "TN", execution,null)
199 saveSliceProfile(execution,"TN",sliceProfileTn)
202 if(!sliceTaskParams.getSliceProfileCn()){
203 Map<String, Object> sliceProfileCn = getSliceProfile( "CN", execution,null, )
204 saveSliceProfile(execution,"CN",sliceProfileCn)
207 logger.debug("Finish parseServiceProfile")
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)
217 else if(domain.equalsIgnoreCase("TN")){
218 execution.setVariable("sliceProfileTn", sliceProfile)
219 sliceTaskParams.setSliceProfileTn(sliceProfile)
220 logger.debug("sliceProfileTn: " + sliceProfile)
222 else if(domain.equalsIgnoreCase("CN")){
223 execution.setVariable("sliceProfileCn", sliceProfile)
224 sliceTaskParams.setSliceProfileCn(sliceProfile)
225 logger.debug("sliceProfileCn: " + sliceProfile)
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)
235 else if(domain.equalsIgnoreCase("CN")){
236 sliceTaskParams.setCnSuggestNssiId(nssiId)
237 sliceTaskParams.setCnSuggestNssiName(nssiName)
239 else if(domain.equalsIgnoreCase("TN")){
240 sliceTaskParams.setTnSuggestNssiId(nssiId)
241 sliceTaskParams.setTnSuggestNssiName(nssiName)
245 private Map getSliceProfile(String domain, DelegateExecution execution, Map<String, Object> oofSliceProfile) {
247 Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
248 Integer domainLatency = (Integer) serviceProfile.get("latency")/3
250 if(domain.equalsIgnoreCase("AN")){
251 profileMapStr = """ {
252 "latency": ${domainLatency},
254 "uEMobilityLevel": "uEMobilityLevel",
255 "coverageAreaTAList": "coverageAreaTAList",
259 else if(domain.equalsIgnoreCase("TN")){
261 "latency":${domainLatency},
263 "e2eLatency":"latency",
267 else if(domain.equalsIgnoreCase("CN")){
268 profileMapStr = """ {
269 "areaTrafficCapDL":"areaTrafficCapDL",
270 "maxNumberofUEs":"maxNumberofUEs",
271 "latency":${domainLatency},
272 "expDataRateUL":"expDataRateUL",
274 "areaTrafficCapUL":"areaTrafficCapUL",
275 "uEMobilityLevel":"uEMobilityLevel",
276 "expDataRateDL":"expDataRateDL",
277 "activityFactor":"activityFactor",
278 "resourceSharingLevel":"resourceSharingLevel"
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)}")
292 else if(serviceProfile.keySet().contains(value)){
293 sliceProfile.put(key, serviceProfile.get(value))
296 sliceProfile.put(key, profileMaps.get(key))
302 void processDecomposition(DelegateExecution execution){
303 logger.debug("Start processDecomposition")
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)
312 logger.debug("End processDecomposition")
316 void prepareNSTDecompose(DelegateExecution execution) {
318 String modelUuid = execution.getVariable("nstModelUuid")
319 String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
321 String serviceModelInfo = """{
322 "modelInvariantUuid":"${modelInvariantUuid}",
323 "modelUuid":"${modelUuid}",
326 execution.setVariable("serviceModelInfo", serviceModelInfo)
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}",
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)
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)
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()")
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 =""
386 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
387 logger.debug( "get NSI option OOF Url: " + urlString)
388 boolean isNSISuggested = false
389 execution.setVariable("isNSISuggested",isNSISuggested)
391 //Prepare auth for OOF - Begin
393 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
394 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
396 String basicAuthValue = utils.encrypt(basicAuth, msokey)
397 if (basicAuthValue != null) {
398 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
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")
408 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
409 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
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}"
422 String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
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)
430 int responseCode = httpResponse.getStatus()
431 logger.debug("OOF sync response code is: " + responseCode)
433 if(responseCode != 200){
434 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
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)
445 if(isBlank(nssiInstanceId)){
446 logger.debug( "There is no valid NSST suggested by OOF.")
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()
456 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
459 sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
460 sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
463 sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
464 sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
467 sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
468 sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
473 }catch(NotFoundException e)
475 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
478 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
481 logger.debug("Prepare NSSI option completed ")