1 package org.onap.so.bpmn.infrastructure.scripts
3 import com.fasterxml.jackson.core.type.TypeReference
4 import com.fasterxml.jackson.databind.ObjectMapper
5 import groovy.json.JsonSlurper
6 import org.camunda.bpm.engine.delegate.DelegateExecution
7 import org.onap.logging.filter.base.ONAPComponents
8 import org.onap.so.beans.nsmf.SliceTaskParams
9 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
10 import org.onap.so.bpmn.common.scripts.ExceptionUtil
11 import org.onap.so.bpmn.common.scripts.OofUtils
12 import org.onap.so.bpmn.core.UrnPropertiesReader
13 import org.onap.so.bpmn.core.domain.ServiceDecomposition
14 import org.onap.so.bpmn.core.domain.ServiceProxy
15 import org.onap.so.bpmn.core.json.JsonUtils
16 import org.onap.so.client.HttpClient
17 import org.onap.so.client.HttpClientFactory
18 import org.onap.aaiclient.client.aai.AAIObjectType
19 import org.onap.aaiclient.client.aai.AAIResourcesClient
20 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
21 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
22 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
23 import org.slf4j.Logger
24 import org.slf4j.LoggerFactory
25 import javax.ws.rs.NotFoundException
26 import javax.ws.rs.core.Response
28 import static org.apache.commons.lang3.StringUtils.isBlank
30 public class DoCreateSliceServiceOption extends AbstractServiceTaskProcessor{
32 private static final Logger logger = LoggerFactory.getLogger( DoCreateSliceServiceOption.class)
34 ExceptionUtil exceptionUtil = new ExceptionUtil()
36 JsonUtils jsonUtil = new JsonUtils()
38 OofUtils oofUtils = new OofUtils()
40 ObjectMapper objectMapper = new ObjectMapper()
42 void preProcessRequest (DelegateExecution execution) {
46 void getNSIOptionfromOOF(DelegateExecution execution) {
49 logger.debug("start parseServiceProfile")
50 parseServiceProfile(execution)
51 logger.debug("end parseServiceProfile")
53 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
54 logger.debug( "get NSI option OOF Url: " + urlString)
56 boolean isNSISuggested = true
57 execution.setVariable("isNSISuggested",isNSISuggested)
59 //Prepare auth for OOF - Begin
61 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
62 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
64 String basicAuthValue = utils.encrypt(basicAuth, msokey)
65 if (basicAuthValue != null) {
66 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
68 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
69 execution.setVariable("BasicAuthHeaderValue", authHeader)
70 } catch (Exception ex) {
71 logger.debug( "Unable to encode username and password string: " + ex)
72 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
73 "encode username and password string")
76 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
77 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
80 //Prepare auth for OOF - End
82 String requestId = execution.getVariable("msoRequestId")
83 Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
84 Map<String, Object> nstSolution = execution.getVariable("nstSolution")
85 logger.debug("Get NST selection from OOF: " + nstSolution.toString())
87 "modelInvariantId":"${nstSolution.invariantUUID}",
88 "modelVersionId":"${nstSolution.UUID}",
89 "modelName":"${nstSolution.NSTName}"
92 String oofRequest = oofUtils.buildSelectNSIRequest(requestId, nstInfo, profileInfo)
93 logger.debug("Sending request to OOF: " + oofRequest)
95 //send request to get NSI option - Begin
96 URL url = new URL(urlString+"/api/oof/selection/nsi/v1")
97 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
98 httpClient.addAdditionalHeader("Authorization", authHeader)
99 Response httpResponse = httpClient.post(oofRequest)
101 processOOFResponse(httpResponse, execution)
104 private void processOOFResponse(Response httpResponse, DelegateExecution execution) {
105 int responseCode = httpResponse.getStatus()
106 logger.debug("OOF sync response code is: " + responseCode)
108 if (responseCode != 200) {
109 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
110 logger.debug("Info: No NSI suggested by OOF")
113 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
114 if (httpResponse.hasEntity()) {
115 String OOFResponse = httpResponse.readEntity(String.class)
116 logger.debug("NSI OOFResponse is: " + OOFResponse)
117 execution.setVariable("OOFResponse", OOFResponse)
119 //This needs to be changed to derive a value when we add policy to decide the solution options.
120 Map OOFResponseObject = new JsonSlurper().parseText(OOFResponse)
121 Map solutions = OOFResponseObject.get("solutions")
123 Boolean isSharable = false
124 String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
125 if (resourceSharingLevel.equals("shared"))
128 if (solutions != null) {
131 processSharedNSISolutions(solutions, execution)
133 //TODO test OOF don't implement in Frankfurt release
134 if (solutions.containsKey("newNSISolutions")) {
135 List<Map> newNSISolutions = solutions.get("newNSISolutions")
136 List<Map> NSSImap = new ArrayList<>()
137 if (newNSISolutions != null && newNSISolutions.size() > 0) {
138 NSSImap = newNSISolutions.get(index).get("NSSISolutions") as List<Map>
140 for (Map nssi : NSSImap) {
141 def nssiSolution = nssi.get("NSSISolution") as Map<String, ?>
142 String nssiName = nssiSolution.getOrDefault("NSSIName", "")
143 String nssiId = nssiSolution.getOrDefault("NSSIId", "")
144 String domain = nssiSolution.getOrDefault("domainName", "").toString().toUpperCase()
147 sliceTaskParams.setAnSuggestNssiId(nssiId)
148 sliceTaskParams.setAnSuggestNssiName(nssiName)
151 sliceTaskParams.setCnSuggestNssiId(nssiId)
152 sliceTaskParams.setCnSuggestNssiName(nssiName)
155 sliceTaskParams.setTnSuggestNssiId(nssiId)
156 sliceTaskParams.setTnSuggestNssiName(nssiName)
166 execution.setVariable("sliceTaskParams", sliceTaskParams)
167 logger.debug("Info: No NSI suggested by OOF")
169 logger.debug("*** Completed options Call to OOF ***")
172 private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
173 if (!solutions.containsKey("sharedNSISolutions"))
175 logger.error("OOF don't return sharedNSISolutions")
178 String nsiName, nsiInstanceId, nssiId, nssiName
180 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
182 Map sharedNSIsolution = ((List) solutions.get("sharedNSISolutions")).get(0)
183 nsiInstanceId = sharedNSIsolution.getOrDefault("NSIId", "")
184 nsiName = sharedNSIsolution.getOrDefault("NSIName", "")
185 sliceTaskParams.setNstId(nsiInstanceId)
186 sliceTaskParams.setSuggestNsiName(nsiName)
188 //Temporary modification
189 List NSSIs = sharedNSIsolution.get("NSSIs")
191 Map nssi = NSSIs.get(0)
192 nssiId = nssi.getOrDefault("NSSIId","")
193 nssiName = nssi.getOrDefault("NSSIName","")
194 sliceTaskParams.setCnSuggestNssiId(nssiId)
195 sliceTaskParams.setCnSuggestNssiName(nssiName)
196 sliceProfile = ((List)nssi.get("sliceProfile"))?.get(0)
197 // execution.setVariable("sliceProfileCn", sliceProfile)
198 // sliceTaskParams.setSliceProfileCn(sliceProfile)
200 logger.debug("OOF sharedNSISolution nsiInstanceId:${nsiInstanceId}, nsiName:${nsiName}, nssiId:${nssiId}, nssiName:${nssiName}")
201 logger.debug("OOF SliceProfile:"+sliceProfile.toString())
204 void parseServiceProfile(DelegateExecution execution) {
205 logger.debug("Start parseServiceProfile")
206 String serviceType = execution.getVariable("serviceType")
207 Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
209 // set sliceProfile for three domains
210 Map<String, Object> sliceProfileTn = getSliceProfile(serviceType, "TN", serviceProfile)
211 Map<String, Object> sliceProfileCn = getSliceProfile(serviceType, "CN", serviceProfile)
212 Map<String, Object> sliceProfileAn = getSliceProfile(serviceType, "AN", serviceProfile)
214 execution.setVariable("sliceProfileTn", sliceProfileTn)
215 execution.setVariable("sliceProfileCn", sliceProfileCn)
216 execution.setVariable("sliceProfileAn", sliceProfileAn)
217 logger.debug("sliceProfileTn: " + sliceProfileTn)
218 logger.debug("sliceProfileCn: " + sliceProfileCn)
219 logger.debug("sliceProfileAn: " + sliceProfileAn)
221 logger.debug("Finish parseServiceProfile")
224 Map getSliceProfile(String serviceType, String domain, Map<String, Object> serviceProfile) {
225 //String variablePath = "nsmf." + serviceType + ".profileMap" + domain
226 //String profileMapStr = UrnPropertiesReader.getVariable(variablePath)
227 String profileMapStr = """ {
228 "skip_post_instantiation_configuration":"skip_post_instantiation_configuration",
229 "controller_actor":"controller_actor",
230 "areaTrafficCapDL":"areaTrafficCapDL",
231 "maxNumberofUEs":"maxNumberofUEs",
233 "expDataRateUL":"expDataRateUL",
235 "plmnIdList":"plmnIdList",
237 "areaTrafficCapUL":"areaTrafficCapUL",
238 "uEMobilityLevel":"uEMobilityLevel",
239 "expDataRateDL":"expDataRateDL",
240 "coverageAreaTAList":"coverageAreaTAList",
241 "activityFactor":"activityFactor",
242 "resourceSharingLevel":"resourceSharingLevel"
244 """.trim().replaceAll(" ", "")
245 logger.debug("Profile map for " + domain + " : " + profileMapStr)
246 Map<String, String> profileMaps = objectMapper.readValue(profileMapStr, new TypeReference<Map<String, String>>(){})
247 Map<String, Object> sliceProfileTn = [:]
248 for (Map.Entry<String, String> profileMap : profileMaps) {
249 sliceProfileTn.put(profileMap.key, serviceProfile.get(profileMap.value))
252 return sliceProfileTn
255 void processDecomposition(DelegateExecution execution){
256 logger.debug("Start processDecomposition")
258 ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
259 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
260 String nstName = serviceDecomposition.getModelInfo().getModelName()
261 sliceTaskParams.setNstName(nstName)
262 String nstId = serviceDecomposition.getModelInfo().getModelUuid()
263 sliceTaskParams.setNstId(nstId)
265 logger.debug("End processDecomposition")
269 void prepareNSTDecompose(DelegateExecution execution) {
271 String modelUuid = execution.getVariable("nstModelUuid")
272 String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
274 String serviceModelInfo = """{
275 "modelInvariantUuid":"${modelInvariantUuid}",
276 "modelUuid":"${modelUuid}",
279 execution.setVariable("serviceModelInfo", serviceModelInfo)
282 void prepareNSSTDecompose(DelegateExecution execution) {
283 Boolean isMoreNSSTtoProcess = false
284 Integer maxNSST = execution.getVariable("maxNSST")
285 Integer currentNSST=execution.getVariable("currentNSST")
286 List<String> nsstModelUUIDList = new ArrayList<>()
287 nsstModelUUIDList = execution.getVariable("nsstModelUUIDList")
288 String modelUuid = nsstModelUUIDList.get(currentNSST)
289 String serviceModelInfo = """{
290 "modelInvariantUuid":"",
291 "modelUuid":"${modelUuid}",
294 execution.setVariable("serviceModelInfo", serviceModelInfo)
295 currentNSST=currentNSST+1
296 if(currentNSST<maxNSST)
297 isMoreNSSTtoProcess=true
298 execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
299 execution.setVariable("maxNSST",maxNSST)
300 execution.setVariable("currentNSST",currentNSST)
304 void prepareNSSTlistfromNST(DelegateExecution execution) {
305 //Need to update this part from decomposition.
306 logger.trace("Enter prepareNSSTlistfromNST()")
307 Boolean isMoreNSSTtoProcess = false
308 ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
309 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
310 String nstName = serviceDecomposition.getModelInfo().getModelName()
311 sliceTaskParams.setNstName(nstName)
312 String nstId = serviceDecomposition.getModelInfo().getModelUuid()
313 sliceTaskParams.setNstId(nstId)
314 execution.setVariable("sliceTaskParams",sliceTaskParams)
316 List<ServiceProxy> proxyList = serviceDecomposition.getServiceProxy()
317 List<String> nsstModelUUIDList = new ArrayList<>()
318 for(ServiceProxy serviceProxy:proxyList)
319 nsstModelUUIDList.add(serviceProxy.getSourceModelUuid())
320 execution.setVariable("nsstModelUUIDList",nsstModelUUIDList)
321 Integer maxNSST = nsstModelUUIDList.size()
322 Integer currentNSST=0
323 execution.setVariable("maxNSST",maxNSST)
324 execution.setVariable("currentNSST",currentNSST)
325 if(currentNSST<maxNSST)
326 isMoreNSSTtoProcess=true
327 execution.setVariable("isMoreNSSTtoProcess",isMoreNSSTtoProcess)
328 logger.trace("Exit prepareNSSTlistfromNST()")
332 void getNSSTOption(DelegateExecution execution) {
333 ServiceDecomposition serviceDecomposition= execution.getVariable("serviceDecomposition")
334 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
335 String globalSubscriberId = execution.getVariable("globalSubscriberId")
336 String serviceType = execution.getVariable("subscriptionServiceType")
337 String nssiInstanceId =""
339 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
340 logger.debug( "get NSI option OOF Url: " + urlString)
341 boolean isNSISuggested = false
342 execution.setVariable("isNSISuggested",isNSISuggested)
344 //Prepare auth for OOF - Begin
346 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
347 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
349 String basicAuthValue = utils.encrypt(basicAuth, msokey)
350 if (basicAuthValue != null) {
351 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
353 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
354 execution.setVariable("BasicAuthHeaderValue", authHeader)
355 } catch (Exception ex) {
356 logger.debug( "Unable to encode username and password string: " + ex)
357 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to " +
358 "encode username and password string")
361 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
362 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
365 //Prepare auth for OOF - End
366 //Prepare send request to OOF - Begin
367 String requestId = execution.getVariable("msoRequestId")
368 Map<String, Object> profileInfo = execution.getVariable("serviceProfile")
369 String nsstModelInvariantUuid = serviceDecomposition.getModelInfo().getModelInvariantUuid()
370 String nsstModelUuid = serviceDecomposition.getModelInfo().getModelUuid()
371 String nsstInfo = """"NSSTInfo": {
372 "invariantUUID":"${nsstModelInvariantUuid}",
373 "UUID":"${nsstModelUuid}"
375 String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
378 URL url = new URL(urlString+"/api/oof/v1/selectnssi")
379 HttpClient httpClient = new HttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
380 httpClient.addAdditionalHeader("Authorization", authHeader)
381 Response httpResponse = httpClient.post(oofRequest)
383 int responseCode = httpResponse.getStatus()
384 logger.debug("OOF sync response code is: " + responseCode)
386 if(responseCode != 200){
387 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
390 if(httpResponse.hasEntity()){
391 String OOFResponse = httpResponse.readEntity(String.class)
392 execution.setVariable("OOFResponse", OOFResponse)
393 nssiInstanceId = jsonUtil.getJsonValue(OOFResponse, "NSSIIInfo.NSSIID")
394 nssiName = jsonUtil.getJsonValue(OOFResponse, "NSSIInfo.NSSIName")
395 execution.setVariable("nssiInstanceId",nssiInstanceId)
396 execution.setVariable("nssiName",nssiName)
398 if(isBlank(nssiInstanceId)){
399 logger.debug( "There is no valid NSST suggested by OOF.")
403 AAIResourcesClient resourceClient = new AAIResourcesClient()
404 AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalSubscriberId, serviceType, nssiInstanceId)
405 AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
406 Optional<org.onap.aai.domain.yang.ServiceInstance> si = wrapper.asBean(org.onap.aai.domain.yang.ServiceInstance.class)
407 org.onap.aai.domain.yang.ServiceInstance nssi = si.get()
409 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
412 sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
413 sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
416 sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
417 sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
420 sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
421 sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
426 }catch(NotFoundException e)
428 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
431 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
434 logger.debug("Prepare NSSI option completed ")