2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 Telecom Italia
6 * ================================================================================
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.databind.ObjectMapper
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.json.JSONArray
27 import org.json.JSONObject
28 import org.onap.aai.domain.yang.v19.ModelVer
29 import org.onap.aai.domain.yang.v19.ServiceInstance
30 import org.onap.aai.domain.yang.v19.SliceProfile
31 import org.onap.aaiclient.client.aai.AAIResourcesClient
32 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper
33 import org.onap.aaiclient.client.aai.entities.Relationships
34 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri
35 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory
36 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder
37 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types
38 import org.onap.logging.filter.base.ONAPComponents
39 import org.onap.so.bpmn.common.scripts.ExceptionUtil
40 import org.onap.so.bpmn.common.scripts.ExternalAPIUtil
41 import org.onap.so.bpmn.common.scripts.ExternalAPIUtilFactory
42 import org.onap.so.bpmn.common.scripts.MsoUtils
43 import org.onap.so.bpmn.common.scripts.OofUtils
44 import org.onap.so.bpmn.common.scripts.RequestDBUtil
45 import org.onap.so.bpmn.core.UrnPropertiesReader
46 import org.onap.so.bpmn.core.json.JsonUtils
47 import org.onap.so.client.HttpClient
48 import org.slf4j.Logger
49 import org.slf4j.LoggerFactory
51 import javax.ws.rs.core.Response
53 import static org.onap.so.bpmn.common.scripts.GenericUtils.isBlank
55 class DoDeallocateCoreNSSI extends DoCommonCoreNSSI {
56 private final String PREFIX ="DoDeallocateCoreNSSI"
57 private final String ACTION = "Deallocate"
59 private ExceptionUtil exceptionUtil = new ExceptionUtil()
60 private RequestDBUtil requestDBUtil = new RequestDBUtil()
61 private MsoUtils utils = new MsoUtils()
62 private JsonUtils jsonUtil = new JsonUtils()
64 private static final Logger LOGGER = LoggerFactory.getLogger( DoDeallocateCoreNSSI.class)
68 void preProcessRequest(DelegateExecution execution) {
69 LOGGER.debug("${getPrefix()} Start preProcessRequest")
71 super.preProcessRequest(execution)
73 execution.setVariable("operationType", "DEALLOCATE")
75 LOGGER.debug("${getPrefix()} Exit preProcessRequest")
81 * Queries OOF for NSSI termination
84 void executeTerminateNSSIQuery(DelegateExecution execution) {
85 LOGGER.debug("${PREFIX} Start executeTerminateNSSIQuery")
87 String urlString = UrnPropertiesReader.getVariable("mso.oof.endpoint", execution)
90 String apiPath = "/api/oof/terminate/nxi/v1"
91 LOGGER.debug("API path for DoAllocateCoreNSSI: "+apiPath)
93 urlString = urlString + apiPath
95 //Prepare auth for OOF
97 String basicAuth = UrnPropertiesReader.getVariable("mso.oof.auth", execution)
98 String msokey = UrnPropertiesReader.getVariable("mso.msoKey", execution)
100 String basicAuthValue = utils.encrypt(basicAuth, msokey)
103 authHeader = utils.getBasicAuth(basicAuthValue, msokey)
104 execution.setVariable("BasicAuthHeaderValue", authHeader)
105 } catch (Exception ex) {
106 LOGGER.error( "Unable to encode username and password string: " + ex)
107 exceptionUtil.buildAndThrowWorkflowException(execution, 401, "Internal Error - Unable to encode username and password string")
110 //Prepare send request to OOF
111 String oofRequest = buildOOFRequest(execution)
113 String callOOFResponse = callOOF(urlString, authHeader, oofRequest)
114 LOGGER.debug("callOOFResponse=" + callOOFResponse)
116 String errorCode = jsonUtil.getJsonValue(callOOFResponse, "errorCode")
117 if(errorCode == null || errorCode.isEmpty()) { // No error
118 String terminateNSSI = jsonUtil.getJsonValue(callOOFResponse, "terminateResponse")
119 LOGGER.debug("isTerminateNSSI=" + terminateNSSI)
121 execution.setVariable("isTerminateNSSI", terminateNSSI)
124 LOGGER.error(jsonUtil.getJsonValue(callOOFResponse, "errorMessage"))
125 exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(callOOFResponse, "errorMessage"))
128 LOGGER.debug("${PREFIX} Exit executeTerminateNSSIQuery")
133 * Executes sync call to OOF
134 * @return OOF response
136 String callOOF(String urlString, String authHeader, String oofRequest) {
137 LOGGER.debug("${PREFIX} Start callOOF")
139 String errorCode = ""
140 String errorMessage = ""
144 URL url = new URL(urlString)
145 HttpClient httpClient = getHttpClientFactory().newJsonClient(url, ONAPComponents.OOF)
146 httpClient.addAdditionalHeader("Authorization", authHeader)
147 httpClient.addAdditionalHeader("Content-Type", "application/json")
149 Response httpResponse = httpClient.post(oofRequest)
151 int responseCode = httpResponse.getStatus()
152 LOGGER.debug("OOF sync response code is: " + responseCode)
154 if(responseCode < 200 || responseCode >= 300) { // Wrong code
155 errorCode = responseCode
156 errorMessage = "Received a Bad Sync Response from OOF."
159 " \"errorCode\": \"${errorCode}\",\n" +
160 " \"errorMessage\": \"${errorMessage}\"\n" +
164 if (httpResponse.hasEntity()) {
165 response = httpResponse.readEntity(String.class)
169 errorMessage = "No response received from OOF."
172 " \"errorCode\": \"${errorCode}\",\n" +
173 " \"errorMessage\": \"${errorMessage}\"\n" +
179 errorMessage = e.getMessage()
182 " \"errorCode\": \"${errorCode}\",\n" +
183 " \"errorMessage\": \"${errorMessage}\"\n" +
187 LOGGER.debug("${PREFIX} Exit callOOF")
198 private String buildOOFRequest(DelegateExecution execution) {
199 LOGGER.debug("${PREFIX} Start buildOOFRequest")
201 def currentNSSI = execution.getVariable("currentNSSI")
203 String nssiId = currentNSSI['nssiId']
205 ServiceInstance nssi = null
207 AAIResourcesClient client = getAAIClient()
210 AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
211 Optional<ServiceInstance> nssiOpt = client.get(ServiceInstance.class, nssiUri)
213 if (nssiOpt.isPresent()) {
217 String msg = "NSSI service instance not found in AAI for nssi id " + nssiId
219 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
224 String nsiId = currentNSSI['nsiId']
225 ServiceInstance nsi = null
226 AAIResourceUri nsiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nsiId))
227 Optional<ServiceInstance> nsiOpt = client.get(ServiceInstance.class, nsiUri)
228 if (nsiOpt.isPresent()) {
232 String msg = "NSI service instance not found in AAI for nsi id " + nsiId
234 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
238 //Setting correlator as requestId
239 String requestId = execution.getVariable("msoRequestId")
240 execution.setVariable("NSSI_correlator", requestId)
242 //Setting messageType for all Core slice as cn
243 String messageType = "cn"
244 execution.setVariable("NSSI_messageType", messageType)
247 String timeout = execution.getVariable("timeout")
248 if (isBlank(timeout)) {
249 timeout = UrnPropertiesReader.getVariable("mso.oof.timeout", execution);
250 if (isBlank(timeout)) {
255 String nxlId = nssi.getServiceInstanceId()
256 String nxlType = "NSSI"
257 String oofRequest = getOofUtils().buildTerminateNxiRequest(requestId, nxlId, nxlType, messageType, nsi.getServiceInstanceId())
258 LOGGER.debug("**** Terminate Nxi Request: "+oofRequest)
260 LOGGER.debug("${PREFIX} Exit buildOOFRequest")
267 * Prepares ServiceOrderRequest
270 private void prepareServiceOrderRequest(DelegateExecution execution) {
271 LOGGER.debug("${PREFIX} Start prepareServiceOrderRequest")
273 def currentNSSI = execution.getVariable("currentNSSI")
275 //extAPI path hardcoded for testing purposes, will be updated in next patch
276 String extAPIPath = "https://nbi.onap:8443/nbi/api/v4" + "/serviceOrder"
277 execution.setVariable("ExternalAPIURL", extAPIPath)
278 ObjectMapper objectMapper = new ObjectMapper();
279 Map<String, Object> serviceOrder = new LinkedHashMap()
281 serviceOrder.put("externalId", "ONAP001")
283 //Requested Start Date
284 String requestedStartDate = utils.generateCurrentTimeInUtc()
285 String requestedCompletionDate = utils.generateCurrentTimeInUtc()
286 serviceOrder.put("requestedStartDate", requestedStartDate)
287 serviceOrder.put("requestedCompletionDate", requestedCompletionDate)
289 //RelatedParty Fields
290 String relatedPartyId = execution.getVariable("globalSubscriberId")
291 String relatedPartyRole = "ONAPcustomer"
292 Map<String, String> relatedParty = new LinkedHashMap()
293 relatedParty.put("id", relatedPartyId)
294 relatedParty.put("role", relatedPartyRole)
295 List<Map<String, String>> relatedPartyList = new ArrayList()
296 relatedPartyList.add(relatedParty)
297 serviceOrder.put("relatedParty", relatedPartyList)
299 Map<String, Object> orderItem = new LinkedHashMap()
301 String orderItemId = "1"
302 orderItem.put("id", orderItemId)
304 //order item action will always be delete as we are triggering request for deletion
305 String orderItemAction = "delete"
306 orderItem.put("action", orderItemAction)
309 AAIResourcesClient client = getAAIClient()
310 ServiceInstance networkServiceInstance = (ServiceInstance)currentNSSI['networkServiceInstance'] //(ServiceInstance) currentNSSI['nssi']
311 AAIResourceUri modelVerUrl = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.serviceDesignAndCreation().model(networkServiceInstance.getModelInvariantId()).modelVer(networkServiceInstance.getModelVersionId()))
313 Map<String, Object> service = new LinkedHashMap()
315 service.put("id", networkServiceInstance.getServiceInstanceId())
318 String serviceName = networkServiceInstance.getServiceInstanceName()
319 service.put("name", serviceName)
322 service.put("serviceType", networkServiceInstance.getServiceType())
324 service.put("serviceState", "active")
326 Map<String, String> serviceSpecification = new LinkedHashMap()
327 String modelUuid = networkServiceInstance.getModelVersionId()
328 serviceSpecification.put("id", modelUuid)
329 service.put("serviceSpecification", serviceSpecification)
331 orderItem.put("service", service)
332 List<Map<String, String>> orderItemList = new ArrayList()
333 orderItemList.add(orderItem)
334 serviceOrder.put("orderItem", orderItemList)
335 String jsonServiceOrder = objectMapper.writeValueAsString(serviceOrder)
336 LOGGER.debug("******* ServiceOrder :: "+jsonServiceOrder)
337 execution.setVariable("serviceOrderRequest", jsonServiceOrder)
339 LOGGER.debug("${PREFIX} End prepareServiceOrderRequest")
345 * Invokes deleteServiceOrder external API
348 void deleteServiceOrder(DelegateExecution execution) {
349 LOGGER.debug("${PREFIX} Start deleteServiceOrder")
351 def currentNSSI = execution.getVariable("currentNSSI")
353 prepareServiceOrderRequest(execution)
356 String extAPIPath = execution.getVariable("ExternalAPIURL")
357 String payload = execution.getVariable("serviceOrderRequest")
358 LOGGER.debug("externalAPIURL is: " + extAPIPath)
359 LOGGER.debug("ServiceOrder payload is: " + payload)
361 execution.setVariable("ServiceOrderId", "")
363 String callDeleteServiceOrderResponse = callDeleteServiceOrder(execution, extAPIPath, payload)
364 String errorCode = jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorCode")
366 if(errorCode == null || errorCode.isEmpty()) { // No error
367 JSONObject responseObj = new JSONObject(callDeleteServiceOrderResponse)
369 String serviceOrderId = responseObj.get("id")
371 execution.setVariable("ServiceOrderId", serviceOrderId)
372 LOGGER.info("Delete ServiceOrderid is: " + serviceOrderId)
375 LOGGER.error(jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorMessage"))
376 exceptionUtil.buildAndThrowWorkflowException(execution, Integer.parseInt(errorCode), jsonUtil.getJsonValue(callDeleteServiceOrderResponse, "errorMessage"))
379 }catch (BpmnError e) {
381 } catch (Exception ex) {
382 String msg = "Exception in ServiceOrder ExtAPI" + ex.getMessage()
384 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
387 LOGGER.debug("${PREFIX} Exit deleteServiceOrder")
391 String callDeleteServiceOrder(DelegateExecution execution, String extAPIPath, String payload) {
392 LOGGER.debug("${PREFIX} Start callDeleteServiceOrder")
394 String errorCode = ""
395 String errorMessage = ""
398 LOGGER.debug("callDeleteServiceOrder: url = " + extAPIPath)
401 ExternalAPIUtil externalAPIUtil = getExternalAPIUtil()
402 Response httpResponse = externalAPIUtil.executeExternalAPIPostCall(execution, extAPIPath, payload)
404 int responseCode = httpResponse.getStatus()
405 execution.setVariable("ServiceOrderResponseCode", responseCode)
406 LOGGER.debug("Delete ServiceOrder response code is: " + responseCode)
409 if(responseCode == 200 || responseCode == 201 || responseCode == 202 ) {
410 //200 OK 201 CREATED 202 ACCEPTED
411 LOGGER.debug("Delete ServiceOrder Received a Good Response")
413 response = httpResponse.readEntity(String.class)
415 LOGGER.debug("callDeleteServiceInstance: response = " + response)
417 execution.setVariable("DeleteServiceOrderResponse", response)
422 errorMessage = "Response code is " + responseCode
425 " \"errorCode\": \"${errorCode}\",\n" +
426 " \"errorMessage\": \"${errorMessage}\"\n" +
431 String msg = "Exception in DoDeallocateCoreNSSI.callDeleteServiceOrder. " + any.getCause()
434 " \"errorCode\": \"7000\",\n" +
435 " \"errorMessage\": \"${msg}\"\n" +
439 LOGGER.debug("${PREFIX} Exit callDeleteServiceOrder")
446 * Removes NSSI association with NSI
449 void removeNSSIAssociationWithNSI(DelegateExecution execution) {
450 LOGGER.debug("${PREFIX} Start removeNSSIAssociationWithNSI")
452 AAIResourcesClient client = getAAIClient()
454 def currentNSSI = execution.getVariable("currentNSSI")
456 String nssiId = currentNSSI['nssiId']
457 String nsiId = currentNSSI['nsiId']
458 String globalSubscriberId = execution.getVariable("globalSubscriberId")
459 String subscriptionServiceType = execution.getVariable("subscriptionServiceType")
462 AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
465 String allottedResourceId = null
468 AAIResultWrapper nssiWrapper = client.get(nssiUri)
469 Optional<Relationships> nssiRelationships = nssiWrapper.getRelationships()
471 if (nssiRelationships.isPresent()) {
473 for (AAIResourceUri allottedResourceUri : nssiRelationships.get().getRelatedUris(Types.ALLOTTED_RESOURCE)) {
474 AAIResultWrapper arWrapper = client.get(allottedResourceUri)
475 Optional<Relationships> arRelationships = arWrapper.getRelationships()
477 if(arRelationships.isPresent()) {
479 for (AAIResourceUri nsiUri : arRelationships.get().getRelatedUris(Types.SERVICE_INSTANCE)) {
480 Optional<ServiceInstance> nsiOpt = client.get(ServiceInstance.class, nsiUri)
482 if (nsiOpt.isPresent()) {
483 ServiceInstance nsi = nsiOpt.get()
484 if(nsi.getServiceRole().equals("nsi")) { // Service instance as NSI
485 // Removes NSSI association with NSI
487 client.disconnect(nssiUri, nsiUri)
489 catch (Exception e) {
490 exceptionUtil.buildAndThrowWorkflowException(execution, 25000, "Exception occured while NSSI association with NSI dosconnect call: " + e.getMessage())
495 LOGGER.warn("No NSI found for NSSI id " + nssiId)
500 LOGGER.warn("No relationships found for Allotted Resource for NSSI id " + nssiId)
506 LOGGER.warn("No relationships found for nssi id = " + nssiId)
510 LOGGER.debug("${PREFIX} Exit removeNSSIAssociationWithNSI")
515 * Delets NSSI Service Instance
518 void deleteNSSIServiceInstance(DelegateExecution execution) {
519 LOGGER.debug("${PREFIX} Start deleteNSSIServiceInstance")
521 AAIResourcesClient client = getAAIClient()
523 def currentNSSI = execution.getVariable("currentNSSI")
525 String nssiId = currentNSSI['nssiId']
526 AAIResourceUri nssiUri = AAIUriFactory.createResourceUri(Types.SERVICE_INSTANCE.getFragment(nssiId))
529 client.delete(nssiUri)
531 exceptionUtil.buildAndThrowWorkflowException(execution, 25000, "Exception occurred while NSSI Service Instance delete call: " + e.getMessage())
534 LOGGER.debug("${PREFIX} Exit deleteNSSIServiceInstance")
539 * Gets Delete Service Order progress
542 void getDeleteServiceOrderProgress(DelegateExecution execution) {
543 LOGGER.debug("${getPrefix()} Start getDeleteServiceOrderProgress")
547 String extAPIPath = execution.getVariable("ExternalAPIURL")
548 extAPIPath += "/" + execution.getVariable("ServiceOrderId")
549 LOGGER.debug("externalAPIURL is: " + extAPIPath)
551 ExternalAPIUtil externalAPIUtil = getExternalAPIUtil()
552 Response response = externalAPIUtil.executeExternalAPIGetCall(execution, extAPIPath)
553 int responseCode = response.getStatus()
554 execution.setVariable("GetServiceOrderResponseCode", responseCode)
555 LOGGER.debug("Get ServiceOrder response code is: " + responseCode)
556 String extApiResponse = response.readEntity(String.class)
557 JSONObject responseObj = new JSONObject(extApiResponse)
558 execution.setVariable("GetServiceOrderResponse", extApiResponse)
559 LOGGER.debug("Get response body is: " + extApiResponse)
560 //Process Response //200 OK 201 CREATED 202 ACCEPTED
561 if(responseCode == 200 || responseCode == 201 || responseCode == 202 )
563 LOGGER.debug("Get Delete ServiceOrder Received a Good Response")
564 String orderState = responseObj.get("state")
565 if("REJECTED".equalsIgnoreCase(orderState)) {
566 prepareFailedOperationStatusUpdate(execution)
569 JSONArray items = responseObj.getJSONArray("orderItem")
570 JSONObject item = items.get(0) as JSONObject
571 JSONObject service = item.get("service") as JSONObject
572 String networkServiceId = service.get("id")
574 execution.setVariable("networkServiceId", networkServiceId)
575 String serviceOrderState = item.get("state")
576 execution.setVariable("ServiceOrderState", serviceOrderState)
577 // Get serviceOrder State and process progress
578 if("ACKNOWLEDGED".equalsIgnoreCase(serviceOrderState) || "INPROGRESS".equalsIgnoreCase(serviceOrderState) || "IN_PROGRESS".equalsIgnoreCase(serviceOrderState)) {
579 execution.setVariable("deleteStatus", "processing")
581 else if("COMPLETED".equalsIgnoreCase(serviceOrderState)) {
582 execution.setVariable("deleteStatus", "completed")
584 else if("FAILED".equalsIgnoreCase(serviceOrderState)) {
585 msg = "ServiceOrder failed"
586 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
589 msg = "ServiceOrder failed"
590 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
592 LOGGER.debug("NBI serviceOrder state: "+serviceOrderState)
595 msg = "Get ServiceOrder Received a Bad Response Code. Response Code is: " + responseCode
596 prepareFailedOperationStatusUpdate(execution)
597 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
601 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, e.getMessage())
604 LOGGER.debug("${getPrefix()} Exit getDeleteServiceOrderProgress")
609 * Calculates a final list of S-NSSAI
612 void calculateSNSSAI(DelegateExecution execution) {
613 LOGGER.debug("${getPrefix()} Start calculateSNSSAI")
615 def currentNSSI = execution.getVariable("currentNSSI")
617 List<SliceProfile> associatedProfiles = (List<SliceProfile>)currentNSSI['associatedProfiles']
619 String givenSliceProfileId = currentNSSI['sliceProfileId']
621 List<String> snssais = new ArrayList<>()
623 String isTerminateNSSIVar = execution.getVariable("isTerminateNSSI" )
625 boolean isTerminateNSSI = Boolean.parseBoolean(isTerminateNSSIVar)
627 if(!isTerminateNSSI) { // NSSI should not be terminated
628 LOGGER.debug("calculateSNSSAI: associatedProfiles.size()" + associatedProfiles.size())
629 for (SliceProfile associatedProfile : associatedProfiles) {
630 if (!associatedProfile.getProfileId().equals(givenSliceProfileId)) { // not given profile id
631 LOGGER.debug("calculateSNSSAI: associatedProfile.getSNssai()" + associatedProfile.getSNssai())
632 snssais.add(associatedProfile.getSNssai())
634 currentNSSI['sliceProfileS-NSSAI'] = associatedProfile
639 currentNSSI['S-NSSAIs'] = snssais
641 LOGGER.debug("${getPrefix()} Exit calculateSNSSAI")
647 * @return new OofUtils()
649 OofUtils getOofUtils() {
650 return new OofUtils()
654 private String getPrefix() {
663 ExternalAPIUtil getExternalAPIUtil() {
664 return new ExternalAPIUtilFactory().create()