2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
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=========================================================
20 package org.onap.so.bpmn.infrastructure.scripts
22 import groovy.json.JsonOutput
23 import groovy.json.JsonSlurper
24 import org.apache.commons.lang3.StringUtils
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.json.JSONArray
28 import org.json.JSONObject
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.MsoUtils
32 import org.onap.so.bpmn.core.UrnPropertiesReader
33 import org.onap.so.bpmn.core.WorkflowException
34 import org.onap.so.bpmn.core.domain.Resource
35 import org.onap.so.bpmn.core.domain.ServiceDecomposition
36 import org.onap.so.bpmn.core.json.JsonUtils
37 import org.onap.so.client.HttpClient
38 import org.onap.so.client.HttpClientFactory
39 import org.onap.so.logger.MsoLogger
40 import org.onap.so.utils.TargetEntity
41 import org.springframework.web.util.UriUtils
42 import org.w3c.dom.Document
43 import org.w3c.dom.Node
44 import org.xml.sax.InputSource
46 import javax.ws.rs.core.Response
47 import javax.xml.parsers.DocumentBuilder
48 import javax.xml.parsers.DocumentBuilderFactory
50 import static org.apache.commons.lang3.StringUtils.isBlank
53 * This groovy class supports the <class>DoDeleteE2EServiceInstance.bpmn</class> process.
56 * @param - msoRequestId
57 * @param - globalSubscriberId - O
58 * @param - subscriptionServiceType - O
59 * @param - serviceInstanceId
60 * @param - serviceInstanceName - O
61 * @param - serviceInputParams (should contain aic_zone for serviceTypes TRANSPORT,ATM)
62 * @param - sdncVersion
63 * @param - failNotFound - TODO
64 * @param - serviceInputParams - TODO
66 * @param - delResourceList
67 * @param - serviceRelationShip
70 * @param - WorkflowException
74 public class DoDeleteE2EServiceInstance extends AbstractServiceTaskProcessor {
76 String Prefix="DDEESI_"
77 ExceptionUtil exceptionUtil = new ExceptionUtil()
78 JsonUtils jsonUtil = new JsonUtils()
79 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, DoDeleteE2EServiceInstance.class);
82 public void preProcessRequest (DelegateExecution execution) {
83 msoLogger.debug(" ***** preProcessRequest *****")
87 String requestId = execution.getVariable("msoRequestId")
88 execution.setVariable("prefix",Prefix)
91 //requestDetails.subscriberInfo. for AAI GET & PUT & SDNC assignToplology
92 String globalSubscriberId = execution.getVariable("globalSubscriberId") //globalCustomerId
93 if (globalSubscriberId == null)
95 execution.setVariable("globalSubscriberId", "")
98 //requestDetails.requestParameters. for AAI PUT & SDNC assignTopology
99 String serviceType = execution.getVariable("serviceType")
100 if (serviceType == null)
102 execution.setVariable("serviceType", "")
105 //Generated in parent for AAI PUT
106 String serviceInstanceId = execution.getVariable("serviceInstanceId")
107 if (isBlank(serviceInstanceId)){
108 msg = "Input serviceInstanceId is null"
110 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
113 String sdncCallbackUrl = UrnPropertiesReader.getVariable('URN_mso_workflow_sdncadapter_callback', execution)
114 if (isBlank(sdncCallbackUrl)) {
115 msg = "URN_mso_workflow_sdncadapter_callback is null"
117 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
119 execution.setVariable("sdncCallbackUrl", sdncCallbackUrl)
120 msoLogger.info("SDNC Callback URL: " + sdncCallbackUrl)
122 StringBuilder sbParams = new StringBuilder()
123 Map<String, String> paramsMap = execution.getVariable("serviceInputParams")
125 if (paramsMap != null) {
126 sbParams.append("<service-input-parameters>")
127 for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
129 String paramName = entry.getKey()
130 String paramValue = entry.getValue()
133 <name>${MsoUtils.xmlEscape(paramName)}</name>
134 <value>${MsoUtils.xmlEscape(paramValue)}</value>
137 sbParams.append(paramsXml)
139 sbParams.append("</service-input-parameters>")
141 String siParamsXml = sbParams.toString()
142 if (siParamsXml == null)
144 execution.setVariable("siParamsXml", siParamsXml)
146 } catch (BpmnError e) {
148 } catch (Exception ex){
149 msg = "Exception in preProcessRequest " + ex.getMessage()
151 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
153 msoLogger.debug("***** Exit preProcessRequest *****")
156 public void postProcessAAIGET(DelegateExecution execution) {
157 msoLogger.debug(" ***** postProcessAAIGET ***** ")
161 String serviceInstanceId = execution.getVariable("serviceInstanceId")
162 boolean foundInAAI = execution.getVariable("GENGS_FoundIndicator")
163 String serviceType = ""
166 msoLogger.debug("Found Service-instance in AAI")
168 String siData = execution.getVariable("GENGS_service")
169 msoLogger.debug("SI Data")
172 msg = "Could not retrive ServiceInstance data from AAI to delete id:" + serviceInstanceId
174 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
178 InputSource source = new InputSource(new StringReader(siData));
179 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
180 DocumentBuilder docBuilder = docFactory.newDocumentBuilder()
181 Document serviceXml = docBuilder.parse(source)
182 serviceXml.getDocumentElement().normalize()
183 // get model invariant id
184 // Get Template uuid and version
185 if (utils.nodeExists(siData, "model-invariant-id") && utils.nodeExists(siData, "model-version-id") ) {
186 msoLogger.debug("SI Data model-invariant-id and model-version-id exist")
187 def modelInvariantId = serviceXml.getElementsByTagName("model-invariant-id").item(0).getTextContent()
188 def modelVersionId = serviceXml.getElementsByTagName("model-version-id").item(0).getTextContent()
190 // Set Original Template info
191 execution.setVariable("model-invariant-id-original", modelInvariantId)
192 execution.setVariable("model-version-id-original", modelVersionId)
195 msoLogger.debug("SI Data" + siData)
196 //Confirm there are no related service instances (vnf/network or volume)
197 if (utils.nodeExists(siData, "relationship-list")) {
198 msoLogger.debug("SI Data relationship-list exists")
199 JSONArray jArray = new JSONArray()
201 XmlParser xmlParser = new XmlParser()
202 Node root = xmlParser.parseText(siData)
203 def relation_list = utils.getChildNode(root, 'relationship-list')
204 def relationships = utils.getIdenticalChildren(relation_list, 'relationship')
206 for (def relation: relationships) {
207 def jObj = getRelationShipData(relation, isDebugEnabled)
211 execution.setVariable("serviceRelationShip", jArray.toString())
212 execution.setVariable("serviceRelationShip", jArray.toString())
216 boolean succInAAI = execution.getVariable("GENGS_SuccessIndicator")
218 msoLogger.debug("Error getting Service-instance from AAI :" + serviceInstanceId)
219 WorkflowException workflowException = execution.getVariable("WorkflowException")
220 if(workflowException != null){
221 msoLogger.error("workflowException: " + workflowException)
222 exceptionUtil.buildAndThrowWorkflowException(execution, workflowException.getErrorCode(), workflowException.getErrorMessage())
225 msg = "Failure in postProcessAAIGET GENGS_SuccessIndicator:" + succInAAI
227 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, msg)
231 msoLogger.debug("Service-instance NOT found in AAI. Silent Success")
233 }catch (BpmnError e) {
235 } catch (Exception ex) {
236 msg = "Exception in DoDeleteE2EServiceInstance.postProcessAAIGET. " + ex.getMessage()
238 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
240 msoLogger.debug(" *** Exit postProcessAAIGET *** ")
243 private JSONObject getRelationShipData(node, isDebugEnabled){
244 JSONObject jObj = new JSONObject()
246 def relation = utils.nodeToString(node)
247 def rt = utils.getNodeText(relation, "related-to")
249 def rl = utils.getNodeText(relation, "related-link")
250 msoLogger.debug("ServiceInstance Related NS/Configuration :" + rl)
252 def rl_datas = utils.getIdenticalChildren(node, "relationship-data")
253 for(def rl_data : rl_datas) {
254 def eKey = utils.getChildNodeText(rl_data, "relationship-key")
255 def eValue = utils.getChildNodeText(rl_data, "relationship-value")
257 if ((rt == "service-instance" && eKey.equals("service-instance.service-instance-id"))
258 //for overlay/underlay
259 || (rt == "configuration" && eKey.equals("configuration.configuration-id")
261 jObj.put("resourceInstanceId", eValue)
263 // for sp-partner and others
264 else if(eKey.endsWith("-id")){
265 jObj.put("resourceInstanceId", eValue)
266 String resourceName = rt + eValue;
267 jObj.put("resourceType", resourceName)
270 jObj.put("resourceLinkUrl", rl)
273 def rl_props = utils.getIdenticalChildren(node, "related-to-property")
274 for(def rl_prop : rl_props) {
275 def eKey = utils.getChildNodeText(rl_prop, "property-key")
276 def eValue = utils.getChildNodeText(rl_prop, "property-value")
277 if((rt == "service-instance" && eKey.equals("service-instance.service-instance-name"))
278 //for overlay/underlay
279 || (rt == "configuration" && eKey.equals("configuration.configuration-type"))){
280 jObj.put("resourceType", eValue)
284 msoLogger.debug("Relationship related to Resource:" + jObj.toString())
288 public void getCurrentNS(DelegateExecution execution){
289 utils.log("INFO", "======== Start getCurrentNS Process ======== ", isDebugEnabled)
291 def currentIndex = execution.getVariable("currentNSIndex")
292 List<String> nsSequence = execution.getVariable("nsSequence")
293 String nsResourceType = nsSequence.get(currentIndex)
295 // GET AAI by Name, not ID, for process convenient
296 execution.setVariable("GENGS_type", "service-instance")
297 execution.setVariable("GENGS_serviceInstanceId", "")
298 execution.setVariable("GENGS_serviceInstanceName", nsResourceType)
300 msoLogger.debug("======== COMPLETED getCurrentNS Process ======== ")
303 public void prepareDecomposeService(DelegateExecution execution) {
305 msoLogger.debug(" ***** Inside prepareDecomposeService of create generic e2e service ***** ")
306 String modelInvariantUuid = execution.getVariable("model-invariant-id-original")
307 String modelVersionId = execution.getVariable("model-version-id-original")
309 String serviceModelInfo = """{
310 "modelInvariantUuid":"${modelInvariantUuid}",
311 "modelUuid":"${modelVersionId}",
314 execution.setVariable("serviceModelInfo", serviceModelInfo)
316 msoLogger.debug(" ***** Completed prepareDecomposeService of create generic e2e service ***** ")
317 } catch (Exception ex) {
318 // try error in method block
319 String exceptionMessage = "Bpmn error encountered in create generic e2e service flow. Unexpected Error from method prepareDecomposeService() - " + ex.getMessage()
320 msoLogger.error(exceptionMessage)
321 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
325 private void generateRelatedResourceInfo(String response, JSONObject jObj){
327 def xml = new XmlSlurper().parseText(response)
328 def rtn = xml.childNodes()
329 while (rtn.hasNext()) {
330 groovy.util.slurpersupport.Node node = rtn.next()
331 def key = node.name()
332 def value = node.text()
337 private JSONObject getRelatedResourceInAAI (DelegateExecution execution, JSONObject jObj)
339 msoLogger.debug(" ***** Started getRelatedResourceInAAI *****")
341 String aai_endpoint = UrnPropertiesReader.getVariable("aai.endpoint", execution)
342 String urlLink = jObj.get("resourceLinkUrl")
343 String serviceAaiPath = "${aai_endpoint}${urlLink}"
345 URL url = new URL(serviceAaiPath)
346 HttpClient client = new HttpClientFactory().newXmlClient(url, TargetEntity.AAI)
349 Response response = client.get()
350 int responseCode = response.getStatus()
351 execution.setVariable(Prefix + "GeRelatedResourceResponseCode", responseCode)
352 msoLogger.debug(" Get RelatedResource code is: " + responseCode)
354 String aaiResponse = response.readEntity(String.class)
355 execution.setVariable(Prefix + "GetRelatedResourceResponse", aaiResponse)
358 if(responseCode == 200 || responseCode == 201 || responseCode == 202 )
359 //200 OK 201 CREATED 202 ACCEPTED
361 msoLogger.debug("GET RelatedResource Received a Good Response")
362 execution.setVariable(Prefix + "SuccessIndicator", true)
363 execution.setVariable(Prefix + "FoundIndicator", true)
365 generateRelatedResourceInfo(aaiResponse, jObj)
367 //get model-invariant-uuid and model-uuid
368 String modelInvariantId = ""
369 String modelUuid = ""
370 String modelCustomizationId = ""
371 if(jObj.has("model-invariant-id")) {
372 modelInvariantId = jObj.get("model-invariant-id")
373 modelUuid = jObj.get("model-version-id")
374 modelCustomizationId = jObj.get("model-customization-id")
377 jObj.put("modelInvariantId", modelInvariantId)
378 jObj.put("modelVersionId", modelUuid)
379 jObj.put("modelCustomizationId", modelCustomizationId)
382 String exceptionMessage = "Get RelatedResource Received a Bad Response Code. Response Code is: " + responseCode
383 msoLogger.error(exceptionMessage)
384 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
387 msoLogger.debug(" ***** Exit getRelatedResourceInAAI *****")
391 public void postDecomposeService(DelegateExecution execution) {
392 msoLogger.debug(" ***** Inside processDecomposition() of delete generic e2e service flow ***** ")
394 ServiceDecomposition serviceDecomposition = execution.getVariable("serviceDecomposition")
396 // service model info
397 execution.setVariable("serviceModelInfo", serviceDecomposition.getModelInfo())
399 List<Resource> deleteResourceList = serviceDecomposition.getServiceResources()
400 String serviceRelationShip = execution.getVariable("serviceRelationShip")
401 def jsonSlurper = new JsonSlurper()
402 def jsonOutput = new JsonOutput()
404 List relationShipList = null
405 if (serviceRelationShip != null) {
406 relationShipList = jsonSlurper.parseText(serviceRelationShip)
409 List<Resource> deleteRealResourceList = new ArrayList<Resource>()
411 //Set the real resource instance id to the decomosed resource list
412 //reset the resource instance id , because in the decompose flow ,its a random one.
413 //match the resource-instance-name and the model name
414 if (relationShipList != null) {
415 relationShipList.each {
417 JSONObject obj = getRelatedResourceInAAI(execution, (JSONObject)it)
419 for (Resource resource : deleteResourceList) {
421 String modelName = resource.getModelInfo().getModelName()
423 String modelCustomizationUuid = resource.getModelInfo().getModelCustomizationUuid()
424 if (StringUtils.containsIgnoreCase(obj.get("resourceType"), modelName)) {
425 resource.setResourceId(obj.get("resourceInstanceId"))
426 deleteRealResourceList.add(resource)
428 else if (modelCustomizationUuid.equals(obj.get("modelCustomizationId"))) {
429 resource.setResourceId(obj.get("resourceInstanceId"))
430 resource.setResourceInstanceName(obj.get("resourceType"))
431 deleteRealResourceList.add(resource)
437 // only delete real existing resources
438 execution.setVariable("deleteResourceList", deleteRealResourceList)
440 boolean isDeleteResourceListValid = false
441 if(deleteRealResourceList.size() > 0) {
442 isDeleteResourceListValid = true
444 execution.setVariable("isDeleteResourceListValid", isDeleteResourceListValid)
446 msoLogger.debug("delete resource list : " + deleteRealResourceList)
447 } catch (Exception ex) {
448 String exceptionMessage = "Bpmn error encountered in create generic e2e service flow. processDecomposition() - " + ex.getMessage()
449 msoLogger.error(exceptionMessage)
450 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, exceptionMessage)
452 utils.log("DEBUG", " ***** exit processDecomposition() of delete generic e2e service flow ***** ", isDebugEnabled)
455 public void preInitResourcesOperStatus(DelegateExecution execution){
456 msoLogger.debug(" ======== STARTED preInitResourcesOperStatus Process ======== ")
458 String serviceId = execution.getVariable("serviceInstanceId")
459 String operationId = execution.getVariable("operationId")
460 String operationType = execution.getVariable("operationType")
461 String resourceTemplateUUIDs = ""
462 String result = "processing"
463 String progress = "0"
465 String operationContent = "Prepare service creation"
466 msoLogger.debug("Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId + " operationType:" + operationType)
467 serviceId = UriUtils.encode(serviceId,"UTF-8")
468 execution.setVariable("serviceInstanceId", serviceId)
469 execution.setVariable("operationId", operationId)
470 execution.setVariable("operationType", operationType)
471 List<Resource> deleteResourceList = execution.getVariable("deleteResourceList")
473 String serviceRelationShip = execution.getVariable("serviceRelationShip")
474 for(Resource resource : deleteResourceList){
475 resourceTemplateUUIDs = resourceTemplateUUIDs + resource.getModelInfo().getModelCustomizationUuid() + ":"
478 def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
479 execution.setVariable("URN_mso_adapters_openecomp_db_endpoint", dbAdapterEndpoint)
482 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
483 xmlns:ns="http://org.onap.so/requestsdb">
486 <ns:initResourceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
487 <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
488 <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
489 <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
490 <resourceTemplateUUIDs>${MsoUtils.xmlEscape(resourceTemplateUUIDs)}</resourceTemplateUUIDs>
491 </ns:initResourceOperationStatus>
493 </soapenv:Envelope>"""
495 payload = utils.formatXml(payload)
496 execution.setVariable("CVFMI_initResOperStatusRequest", payload)
497 msoLogger.debug("Outgoing initResourceOperationStatus: \n" + payload)
498 msoLogger.debug("CreateVfModuleInfra Outgoing initResourceOperationStatus Request: " + payload)
501 msoLogger.debug("Exception Occured Processing preInitResourcesOperStatus. Exception is:\n" + e)
502 execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during preInitResourcesOperStatus Method:\n" + e.getMessage())
504 msoLogger.debug("======== COMPLETED preInitResourcesOperStatus Process ======== ")
507 public void prepareUpdateServiceOperationStatus(DelegateExecution execution){
508 msoLogger.debug(" ======== STARTED prepareUpdateServiceOperationStatus Process ======== ")
510 String serviceId = execution.getVariable("serviceInstanceId")
511 String operationId = execution.getVariable("operationId")
513 String result = execution.getVariable("result")
514 String progress = execution.getVariable("progress")
516 String operationContent = execution.getVariable("operationContent")
518 serviceId = UriUtils.encode(serviceId,"UTF-8")
520 def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
521 execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
522 msoLogger.debug("DB Adapter Endpoint is: " + dbAdapterEndpoint)
525 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
526 xmlns:ns="http://org.onap.so/requestsdb">
529 <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
530 <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
531 <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
532 <operationType>DELETE</operationType>
533 <userId>${MsoUtils.xmlEscape(userId)}</userId>
534 <result>${MsoUtils.xmlEscape(result)}</result>
535 <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
536 <progress>${MsoUtils.xmlEscape(progress)}</progress>
537 <reason>${MsoUtils.xmlEscape(reason)}</reason>
538 </ns:updateServiceOperationStatus>
540 </soapenv:Envelope>"""
542 payload = utils.formatXml(payload)
543 execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
544 msoLogger.debug("Outgoing updateServiceOperStatusRequest: \n" + payload)
547 msoLogger.error("Exception Occured Processing prepareUpdateServiceOperationStatus. Exception is:\n" + e)
548 execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during prepareUpdateServiceOperationStatus Method:\n" + e.getMessage())
550 msoLogger.debug("======== COMPLETED prepareUpdateServiceOperationStatus Process ======== ")
554 * post config request.
556 public void postConfigRequest(execution){