2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
22 package org.onap.so.bpmn.infrastructure.scripts
24 import groovy.json.JsonOutput
25 import groovy.json.JsonSlurper
26 import org.apache.commons.lang3.StringUtils
27 import org.camunda.bpm.engine.delegate.BpmnError
28 import org.camunda.bpm.engine.delegate.DelegateExecution
29 import org.json.JSONArray
30 import org.json.JSONObject
31 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
32 import org.onap.so.bpmn.common.scripts.ExceptionUtil
33 import org.onap.so.bpmn.common.scripts.MsoUtils
34 import org.onap.so.bpmn.core.UrnPropertiesReader
35 import org.onap.so.bpmn.core.WorkflowException
36 import org.onap.so.bpmn.core.domain.Resource
37 import org.onap.so.bpmn.core.domain.ServiceDecomposition
38 import org.onap.so.bpmn.core.json.JsonUtils
39 import org.onap.so.client.HttpClient
40 import org.onap.so.client.HttpClientFactory
41 import org.slf4j.Logger
42 import org.slf4j.LoggerFactory
43 import org.onap.so.utils.TargetEntity
44 import org.springframework.web.util.UriUtils
45 import org.w3c.dom.Document
46 import org.w3c.dom.Node
47 import org.xml.sax.InputSource
49 import javax.ws.rs.core.Response
50 import javax.xml.parsers.DocumentBuilder
51 import javax.xml.parsers.DocumentBuilderFactory
53 import static org.apache.commons.lang3.StringUtils.isBlank
56 * This groovy class supports the <class>DoDeleteE2EServiceInstance.bpmn</class> process.
59 * @param - msoRequestId
60 * @param - globalSubscriberId - O
61 * @param - subscriptionServiceType - O
62 * @param - serviceInstanceId
63 * @param - serviceInstanceName - O
64 * @param - serviceInputParams (should contain aic_zone for serviceTypes TRANSPORT,ATM)
65 * @param - sdncVersion
66 * @param - failNotFound - TODO
67 * @param - serviceInputParams - TODO
69 * @param - delResourceList
70 * @param - serviceRelationShip
73 * @param - WorkflowException
77 public class DoDeleteE2EServiceInstance extends AbstractServiceTaskProcessor {
79 String Prefix="DDEESI_"
80 ExceptionUtil exceptionUtil = new ExceptionUtil()
81 JsonUtils jsonUtil = new JsonUtils()
82 private static final Logger logger = LoggerFactory.getLogger( DoDeleteE2EServiceInstance.class);
85 public void preProcessRequest (DelegateExecution execution) {
86 logger.debug(" ***** preProcessRequest *****")
90 String requestId = execution.getVariable("msoRequestId")
91 execution.setVariable("prefix",Prefix)
94 //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology
95 String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId
96 if (globalSubscriberId == null)
98 execution.setVariable("globalSubscriberId", "")
101 //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology
102 String serviceType = execution.getVariable("serviceType")
103 if (serviceType == null)
105 execution.setVariable("serviceType", "")
108 //Generated in parent for AAI PUT
109 String serviceInstanceId = execution.getVariable("serviceInstanceId")
110 if (isBlank(serviceInstanceId)){
111 msg = "Input serviceInstanceId is null"
113 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
116 String sdncCallbackUrl = UrnPropertiesReader.getVariable('URN_mso_workflow_sdncadapter_callback', execution)
117 if (isBlank(sdncCallbackUrl)) {
118 msg = "URN_mso_workflow_sdncadapter_callback is null"
120 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
122 execution.setVariable("sdncCallbackUrl", sdncCallbackUrl)
123 logger.info("SDNC Callback URL: " + sdncCallbackUrl)
125 StringBuilder sbParams = new StringBuilder()
126 Map<String, String> paramsMap = execution.getVariable("serviceInputParams")
128 if (paramsMap != null) {
129 sbParams.append("<service-input-parameters>")
130 for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
132 String paramName = entry.getKey()
133 String paramValue = entry.getValue()
136 <name>${MsoUtils.xmlEscape(paramName)}</name>
137 <value>${MsoUtils.xmlEscape(paramValue)}</value>
140 sbParams.append(paramsXml)
142 sbParams.append("</service-input-parameters>")
144 String siParamsXml = sbParams.toString()
145 if (siParamsXml == null)
147 execution.setVariable("siParamsXml", siParamsXml)
149 } catch (BpmnError e) {
151 } catch (Exception ex){
152 msg = "Exception in preProcessRequest " + ex.getMessage()
154 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
156 logger.debug("***** Exit preProcessRequest *****")
159 public void postProcessAAIGET(DelegateExecution execution) {
160 logger.debug(" ***** postProcessAAIGET ***** ")
164 String serviceInstanceId = execution.getVariable("serviceInstanceId")
165 boolean foundInAAI = execution.getVariable("GENGS_FoundIndicator")
166 String serviceType = ""
169 logger.debug("Found Service-instance in AAI")
171 String siData = execution.getVariable("GENGS_service")
172 logger.debug("SI Data")
175 msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
177 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
181 InputSource source = new InputSource(new StringReader(siData));
182 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
183 DocumentBuilder docBuilder = docFactory.newDocumentBuilder()
184 Document serviceXml = docBuilder.parse(source)
185 serviceXml.getDocumentElement().normalize()
186 // get model invariant id
187 // Get Template uuid and version
188 if (utils.nodeExists(siData, "model-invariant-id") && utils.nodeExists(siData, "model-version-id") ) {
189 logger.debug("SI Data model-invariant-id and model-version-id exist")
190 def modelInvariantId = serviceXml.getElementsByTagName("model-invariant-id").item(0).getTextContent()
191 def modelVersionId = serviceXml.getElementsByTagName("model-version-id").item(0).getTextContent()
193 // Set Original Template info
194 execution.setVariable("model-invariant-id-original", modelInvariantId)
195 execution.setVariable("model-version-id-original", modelVersionId)
198 logger.debug("SI Data" + siData)
199 //Confirm there are no related service instances (vnf/network or volume)
200 if (utils.nodeExists(siData, "relationship-list")) {
201 logger.debug("SI Data relationship-list exists")
202 JSONArray jArray = new JSONArray()
204 XmlParser xmlParser = new XmlParser()
205 Node root = xmlParser.parseText(siData)
206 def relation_list = utils.getChildNode(root, 'relationship-list')
207 def relationships = utils.getIdenticalChildren(relation_list, 'relationship')
209 for (def relation: relationships) {
210 def jObj = getRelationShipData(relation, isDebugEnabled)
214 execution.setVariable("serviceRelationShip", jArray.toString())
215 execution.setVariable("serviceRelationShip", jArray.toString())
219 boolean succInAAI = execution.getVariable("GENGS_SuccessIndicator")
221 logger.debug("Error getting Service-instance from AAI :" + serviceInstanceId)
222 WorkflowException workflowException = execution.getVariable("WorkflowException")
223 if(workflowException != null){
224 logger.error("workflowException: " + workflowException)
225 exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage())
228 msg = "Failure in postProcessAAIGET GENGS_SuccessIndicator:" + succInAAI
230 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
234 logger.debug("Service-instance NOT found in AAI. Silent Success")
236 }catch (BpmnError e) {
238 } catch (Exception ex) {
239 msg = "Exception in DoDeleteE2EServiceInstance.postProcessAAIGET. " + ex.getMessage()
241 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
243 logger.debug(" *** Exit postProcessAAIGET *** ")
246 private JSONObject getRelationShipData(node, isDebugEnabled){
247 JSONObject jObj = new JSONObject()
249 def relation = utils.nodeToString(node)
250 def rt = utils.getNodeText(relation, "related-to")
252 def rl = utils.getNodeText(relation, "related-link")
253 logger.debug("ServiceInstance Related NS/Configuration :" + rl)
255 def rl_datas = utils.getIdenticalChildren(node, "relationship-data")
256 for(def rl_data : rl_datas) {
257 def eKey = utils.getChildNodeText(rl_data, "relationship-key")
258 def eValue = utils.getChildNodeText(rl_data, "relationship-value")
260 if ((rt == "service-instance" && eKey.equals("service-instance.service-instance-id"))
261 //for overlay/underlay
262 || (rt == "configuration" && eKey.equals("configuration.configuration-id")
264 jObj.put("resourceInstanceId", eValue)
266 // for sp-partner and others
267 else if(eKey.endsWith("-id")){
268 jObj.put("resourceInstanceId", eValue)
269 String resourceName = rt + eValue;
270 jObj.put("resourceType", resourceName)
273 jObj.put("resourceLinkUrl", rl)
276 def rl_props = utils.getIdenticalChildren(node, "related-to-property")
277 for(def rl_prop : rl_props) {
278 def eKey = utils.getChildNodeText(rl_prop, "property-key")
279 def eValue = utils.getChildNodeText(rl_prop, "property-value")
280 if((rt == "service-instance" && eKey.equals("service-instance.service-instance-name"))
281 //for overlay/underlay
282 || (rt == "configuration" && eKey.equals("configuration.configuration-type"))){
283 jObj.put("resourceType", eValue)
287 logger.debug("Relationship related to Resource:" + jObj.toString())
291 public void getCurrentNS(DelegateExecution execution){
292 logger.info( "======== Start getCurrentNS Process ======== ")
294 def currentIndex = execution.getVariable("currentNSIndex")
295 List<String> nsSequence = execution.getVariable("nsSequence")
296 String nsResourceType = nsSequence.get(currentIndex)
298 // GET AAI by Name, not ID, for process convenient
299 execution.setVariable("GENGS_type", "service-instance")
300 execution.setVariable("GENGS_serviceInstanceId", "")
301 execution.setVariable("GENGS_serviceInstanceName", nsResourceType)
303 logger.debug("======== COMPLETED getCurrentNS Process ======== ")
306 public void prepareDecomposeService(DelegateExecution execution) {
308 logger.debug(" ***** Inside prepareDecomposeService of create generic e2e service ***** ")
309 String modelInvariantUuid = execution.getVariable("model-invariant-id-original")
310 String modelVersionId = execution.getVariable("model-version-id-original")
312 String serviceModelInfo = """{
313 "modelInvariantUuid":"${modelInvariantUuid}",
314 "modelUuid":"${modelVersionId}",
317 execution.setVariable("serviceModelInfo", serviceModelInfo)
319 logger.debug(" ***** Completed prepareDecomposeService of create generic e2e service ***** ")
320 } catch (Exception ex) {
321 // try error in method block
322 String exceptionMessage = "Bpmn error encountered in create generic e2e service flow. Unexpected Error from method prepareDecomposeService() - " + ex.getMessage()
323 logger.error(exceptionMessage)
324 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
328 private void generateRelatedResourceInfo(String response, JSONObject jObj){
330 def xml = new XmlSlurper().parseText(response)
331 def rtn = xml.childNodes()
332 while (rtn.hasNext()) {
333 groovy.util.slurpersupport.Node node = rtn.next()
334 def key = node.name()
335 def value = node.text()
340 private JSONObject getRelatedResourceInAAI (DelegateExecution execution, JSONObject jObj)
342 logger.debug(" ***** Started getRelatedResourceInAAI *****")
344 String aai_endpoint = UrnPropertiesReader.getVariable("aai.endpoint", execution)
345 String urlLink = jObj.get("resourceLinkUrl")
346 String serviceAaiPath = "${aai_endpoint}${urlLink}"
348 URL url = new URL(serviceAaiPath)
349 HttpClient client = new HttpClientFactory().newXmlClient(url, TargetEntity.AAI)
352 Response response = client.get()
353 int responseCode = response.getStatus()
354 execution.setVariable(Prefix + "GeRelatedResourceResponseCode", responseCode)
355 logger.debug(" Get RelatedResource code is: " + responseCode)
357 String aaiResponse = response.readEntity(String.class)
358 execution.setVariable(Prefix + "GetRelatedResourceResponse", aaiResponse)
361 if(responseCode == 200 || responseCode == 201 || responseCode == 202 )
362 //200 OK 201 CREATED 202 ACCEPTED
364 logger.debug("GET RelatedResource Received a Good Response")
365 execution.setVariable(Prefix + "SuccessIndicator", true)
366 execution.setVariable(Prefix + "FoundIndicator", true)
368 generateRelatedResourceInfo(aaiResponse, jObj)
370 //get model-invariant-uuid and model-uuid
371 String modelInvariantId = ""
372 String modelUuid = ""
373 String modelCustomizationId = ""
374 if(jObj.has("model-invariant-id")) {
375 modelInvariantId = jObj.get("model-invariant-id")
376 modelUuid = jObj.get("model-version-id")
377 modelCustomizationId = jObj.get("model-customization-id")
380 jObj.put("modelInvariantId", modelInvariantId)
381 jObj.put("modelVersionId", modelUuid)
382 jObj.put("modelCustomizationId", modelCustomizationId)
385 String exceptionMessage = "Get RelatedResource Received a Bad Response Code. Response Code is: " + responseCode
386 logger.error(exceptionMessage)
387 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
390 logger.debug(" ***** Exit getRelatedResourceInAAI *****")
394 public void postDecomposeService(DelegateExecution execution) {
395 logger.debug(" ***** Inside processDecomposition() of delete generic e2e service flow ***** ")
397 ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
399 // service model info
400 execution.setVariable("serviceModelInfo", serviceDecomposition.getModelInfo())
402 List<Resource> deleteResourceList = serviceDecomposition.getServiceResources()
403 String serviceRelationShip = execution.getVariable("serviceRelationShip")
404 def jsonSlurper = new JsonSlurper()
405 def jsonOutput = new JsonOutput()
407 List relationShipList = null
408 if (serviceRelationShip != null) {
409 relationShipList = jsonSlurper.parseText(serviceRelationShip)
412 List<Resource> deleteRealResourceList = new ArrayList<Resource>()
414 //Set the real resource instance id to the decomosed resource list
415 //reset the resource instance id , because in the decompose flow ,its a random one.
416 //match the resource-instance-name and the model name
417 if (relationShipList != null) {
418 relationShipList.each {
420 JSONObject obj = getRelatedResourceInAAI(execution, (JSONObject)it)
422 for (Resource resource : deleteResourceList) {
424 String modelName = resource.getModelInfo().getModelName()
426 String modelCustomizationUuid = resource.getModelInfo().getModelCustomizationUuid()
427 if (StringUtils.containsIgnoreCase(obj.get("resourceType"), modelName)) {
428 resource.setResourceId(obj.get("resourceInstanceId"))
429 deleteRealResourceList.add(resource)
431 else if (modelCustomizationUuid.equals(obj.get("modelCustomizationId"))) {
432 resource.setResourceId(obj.get("resourceInstanceId"))
433 resource.setResourceInstanceName(obj.get("resourceType"))
434 deleteRealResourceList.add(resource)
440 // only delete real existing resources
441 execution.setVariable("deleteResourceList", deleteRealResourceList)
443 boolean isDeleteResourceListValid = false
444 if(deleteRealResourceList.size() > 0) {
445 isDeleteResourceListValid = true
447 execution.setVariable("isDeleteResourceListValid", isDeleteResourceListValid)
449 logger.debug("delete resource list : " + deleteRealResourceList)
450 } catch (Exception ex) {
451 String exceptionMessage = "Bpmn error encountered in create generic e2e service flow. processDecomposition() - " + ex.getMessage()
452 logger.error(exceptionMessage)
453 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
455 logger.debug( " ***** exit processDecomposition() of delete generic e2e service flow ***** ")
458 public void preInitResourcesOperStatus(DelegateExecution execution){
459 logger.debug(" ======== STARTED preInitResourcesOperStatus Process ======== ")
461 String serviceId = execution.getVariable("serviceInstanceId")
462 String operationId = execution.getVariable("operationId")
463 String operationType = execution.getVariable("operationType")
464 String resourceTemplateUUIDs = ""
465 String result = "processing"
466 String progress = "0"
468 String operationContent = "Prepare service creation"
469 logger.debug("Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId + " operationType:" + operationType)
470 serviceId = UriUtils.encode(serviceId,"UTF-8")
471 execution.setVariable("serviceInstanceId", serviceId)
472 execution.setVariable("operationId", operationId)
473 execution.setVariable("operationType", operationType)
474 List<Resource> deleteResourceList = execution.getVariable("deleteResourceList")
476 String serviceRelationShip = execution.getVariable("serviceRelationShip")
477 for(Resource resource : deleteResourceList){
478 resourceTemplateUUIDs = resourceTemplateUUIDs + resource.getModelInfo().getModelCustomizationUuid() + ":"
481 def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
482 execution.setVariable("URN_mso_adapters_openecomp_db_endpoint", dbAdapterEndpoint)
485 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
486 xmlns:ns="http://org.onap.so/requestsdb">
489 <ns:initResourceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
490 <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
491 <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
492 <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
493 <resourceTemplateUUIDs>${MsoUtils.xmlEscape(resourceTemplateUUIDs)}</resourceTemplateUUIDs>
494 </ns:initResourceOperationStatus>
496 </soapenv:Envelope>"""
498 payload = utils.formatXml(payload)
499 execution.setVariable("CVFMI_initResOperStatusRequest", payload)
500 logger.debug("Outgoing initResourceOperationStatus: \n" + payload)
501 logger.debug("CreateVfModuleInfra Outgoing initResourceOperationStatus Request: " + payload)
504 logger.debug("Exception Occured Processing preInitResourcesOperStatus. Exception is:\n" + e)
505 execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during preInitResourcesOperStatus Method:\n" + e.getMessage())
507 logger.debug("======== COMPLETED preInitResourcesOperStatus Process ======== ")
510 public void prepareUpdateServiceOperationStatus(DelegateExecution execution){
511 logger.debug(" ======== STARTED prepareUpdateServiceOperationStatus Process ======== ")
513 String serviceId = execution.getVariable("serviceInstanceId")
514 String operationId = execution.getVariable("operationId")
516 String result = execution.getVariable("result")
517 String progress = execution.getVariable("progress")
519 String operationContent = execution.getVariable("operationContent")
521 serviceId = UriUtils.encode(serviceId,"UTF-8")
523 def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
524 execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
525 logger.debug("DB Adapter Endpoint is: " + dbAdapterEndpoint)
528 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
529 xmlns:ns="http://org.onap.so/requestsdb">
532 <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
533 <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
534 <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
535 <operationType>DELETE</operationType>
536 <userId>${MsoUtils.xmlEscape(userId)}</userId>
537 <result>${MsoUtils.xmlEscape(result)}</result>
538 <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
539 <progress>${MsoUtils.xmlEscape(progress)}</progress>
540 <reason>${MsoUtils.xmlEscape(reason)}</reason>
541 </ns:updateServiceOperationStatus>
543 </soapenv:Envelope>"""
545 payload = utils.formatXml(payload)
546 execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
547 logger.debug("Outgoing updateServiceOperStatusRequest: \n" + payload)
550 logger.error("Exception Occured Processing prepareUpdateServiceOperationStatus. Exception is:\n" + e)
551 execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during prepareUpdateServiceOperationStatus Method:\n" + e.getMessage())
553 logger.debug("======== COMPLETED prepareUpdateServiceOperationStatus Process ======== ")
557 * post config request.
559 public void postConfigRequest(execution){