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.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
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) {
70 logger.debug("start parseServiceProfile")
71 parseServiceProfile(execution)
72 logger.debug("end parseServiceProfile")
74 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
75 logger.debug( "get NSI option OOF Url: " + urlString)
77 boolean isNSISuggested = true
78 execution.setVariable("isNSISuggested",isNSISuggested)
80 //Prepare auth for OOF - Begin
82 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
83 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
85 String basicAuthValue = utils.encrypt(basicAuth, msokey)
86 if (basicAuthValue != null) {
87 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
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")
97 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
98 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
101 //Prepare auth for OOF - End
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}"
113 String oofRequest = oofUtils.buildSelectNSIRequest(requestId, nstInfo, profileInfo)
114 logger.debug("Sending request to OOF: " + oofRequest)
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)
122 processOOFResponse(httpResponse, execution)
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 Boolean isSharable = false
145 String resourceSharingLevel = execution.getVariable("resourceSharingLevel")
146 if (resourceSharingLevel.equals("shared"))
149 if (solutions != null) {
152 processSharedNSISolutions(solutions, execution)
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>
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()
168 sliceTaskParams.setAnSuggestNssiId(nssiId)
169 sliceTaskParams.setAnSuggestNssiName(nssiName)
172 sliceTaskParams.setCnSuggestNssiId(nssiId)
173 sliceTaskParams.setCnSuggestNssiName(nssiName)
176 sliceTaskParams.setTnSuggestNssiId(nssiId)
177 sliceTaskParams.setTnSuggestNssiName(nssiName)
187 execution.setVariable("sliceTaskParams", sliceTaskParams)
188 logger.debug("Info: No NSI suggested by OOF")
190 logger.debug("*** Completed options Call to OOF ***")
193 private void processSharedNSISolutions(Map solutions, DelegateExecution execution) {
194 if (!solutions.containsKey("sharedNSISolutions"))
196 logger.error("OOF don't return sharedNSISolutions")
199 String nsiName, nsiInstanceId, nssiId, nssiName
201 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
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)
209 //Temporary modification
210 List NSSIs = sharedNSIsolution.get("NSSIs")
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)
221 logger.debug("OOF sharedNSISolution nsiInstanceId:${nsiInstanceId}, nsiName:${nsiName}, nssiId:${nssiId}, nssiName:${nssiName}")
222 logger.debug("OOF SliceProfile:"+sliceProfile.toString())
225 void parseServiceProfile(DelegateExecution execution) {
226 logger.debug("Start parseServiceProfile")
227 String serviceType = execution.getVariable("serviceType")
228 Map<String, Object> serviceProfile = execution.getVariable("serviceProfile")
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)
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)
242 logger.debug("Finish parseServiceProfile")
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",
254 "expDataRateUL":"expDataRateUL",
256 "plmnIdList":"plmnIdList",
258 "areaTrafficCapUL":"areaTrafficCapUL",
259 "uEMobilityLevel":"uEMobilityLevel",
260 "expDataRateDL":"expDataRateDL",
261 "coverageAreaTAList":"coverageAreaTAList",
262 "activityFactor":"activityFactor",
263 "resourceSharingLevel":"resourceSharingLevel"
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))
273 return sliceProfileTn
276 void processDecomposition(DelegateExecution execution){
277 logger.debug("Start processDecomposition")
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)
286 logger.debug("End processDecomposition")
290 void prepareNSTDecompose(DelegateExecution execution) {
292 String modelUuid = execution.getVariable("nstModelUuid")
293 String modelInvariantUuid = execution.getVariable("nstModelInvariantUuid")
295 String serviceModelInfo = """{
296 "modelInvariantUuid":"${modelInvariantUuid}",
297 "modelUuid":"${modelUuid}",
300 execution.setVariable("serviceModelInfo", serviceModelInfo)
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}",
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)
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)
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()")
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 =""
360 SliceTaskParams sliceTaskParams = execution.getVariable("sliceTaskParams")
361 logger.debug( "get NSI option OOF Url: " + urlString)
362 boolean isNSISuggested = false
363 execution.setVariable("isNSISuggested",isNSISuggested)
365 //Prepare auth for OOF - Begin
367 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
368 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
370 String basicAuthValue = utils.encrypt(basicAuth, msokey)
371 if (basicAuthValue != null) {
372 logger.debug( "Obtained BasicAuth username and password for OOF: " + basicAuthValue)
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")
382 logger.debug( "Unable to obtain BasicAuth - BasicAuth value null")
383 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - BasicAuth " +
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}"
396 String oofRequest = oofUtils.buildSelectNSSIRequest(execution, requestId, nsstInfo ,profileInfo)
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)
404 int responseCode = httpResponse.getStatus()
405 logger.debug("OOF sync response code is: " + responseCode)
407 if(responseCode != 200){
408 exceptionUtil.buildAndThrowWorkflowException(execution, responseCode, "Received a Bad Sync Response from OOF.")
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)
419 if(isBlank(nssiInstanceId)){
420 logger.debug( "There is no valid NSST suggested by OOF.")
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()
430 String domain = nssi.getEnvironmentContext().toString().toUpperCase()
433 sliceTaskParams.setAnSuggestNssiId(nssi.getServiceInstanceId())
434 sliceTaskParams.setAnSuggestNssiName(nssi.getServiceInstanceName())
437 sliceTaskParams.setCnSuggestNssiId(nssi.getServiceInstanceId())
438 sliceTaskParams.setCnSuggestNssiName(nssi.getServiceInstanceName())
441 sliceTaskParams.setTnSuggestNssiId(nssi.getServiceInstanceId())
442 sliceTaskParams.setTnSuggestNssiName(nssi.getServiceInstanceName())
447 }catch(NotFoundException e)
449 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
452 logger.debug("NSSI Service Instance not found in AAI: " + nssiInstanceId)
455 logger.debug("Prepare NSSI option completed ")