cf53aff878ab1147aab635c85dc59328eae048c5
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. 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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  */
22
23 package org.onap.so.bpmn.infrastructure.scripts
24
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.aai.domain.yang.VolumeGroup
28 import org.onap.so.bpmn.common.scripts.AaiUtil;
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.common.scripts.VidUtils;
33 import org.onap.so.bpmn.core.UrnPropertiesReader
34 import org.onap.so.bpmn.core.WorkflowException
35 import org.onap.so.client.aai.AAIObjectType
36 import org.onap.so.client.aai.entities.AAIResultWrapper
37 import org.onap.so.client.aai.entities.uri.AAIResourceUri
38 import org.onap.so.client.aai.entities.uri.AAIUriFactory
39 import org.onap.so.constants.Defaults
40 import org.onap.so.logger.ErrorCode
41 import org.onap.so.logger.MessageEnum
42 import org.slf4j.Logger
43 import org.slf4j.LoggerFactory
44 import groovy.json.JsonSlurper
45
46 import javax.ws.rs.NotFoundException
47
48 /**
49  * This groovy class supports the <class>DeleteVfModuleVolume.bpmn</class> process.
50  */
51 public class DeleteVfModuleVolumeInfraV1 extends AbstractServiceTaskProcessor {
52     private static final Logger logger = LoggerFactory.getLogger( DeleteVfModuleVolumeInfraV1.class);
53
54         private XmlParser xmlParser = new XmlParser()
55         /**
56          * This method is executed during the preProcessRequest task of the <class>DeleteVfModuleVolume.bpmn</class> process.
57          * @param execution
58          */
59         public InitializeProcessVariables(DelegateExecution execution){
60                 execution.setVariable('prefix', 'DELVfModVol_')
61                 execution.setVariable("DELVfModVol_volumeRequest", null)
62                 execution.setVariable('DELVfModVol_requestInfo', null)
63                 execution.setVariable('DELVfModVol_requestId', null)
64                 execution.setVariable('DELVfModVol_source', null)
65                 execution.setVariable('DELVfModVol_volumeInputs', null)
66                 execution.setVariable('DELVfModVol_volumeOutputs', null)
67                 execution.setVariable('DELVfModVol_volumeGroupId', null)
68                 execution.setVariable('DELVfModVol_vnfType', null)
69                 execution.setVariable('DELVfModVol_serviceId', null)
70                 execution.setVariable('DELVfModVol_cloudRegion', null)
71                 execution.setVariable('DELVfModVol_cloudOwner', null)
72                 execution.setVariable('DELVfModVol_tenantId', null)
73                 execution.setVariable('DELVfModVol_volumeParams', null)
74                 execution.setVariable('DELVfModVol_volumeGroupHeatStackId', null)
75                 execution.setVariable('DELVfModVol_volumeGroupTenantId', null)
76                 execution.setVariable("DELVfModVol_queryAAIVolGrpResponse", null)
77                 execution.setVariable('DELVfModVol_messageId', null)
78                 execution.setVariable('DELVfModVol_deleteVnfARequest', null)
79                 execution.setVariable('DELVfModVol_updateInfraRequest', null)
80                 execution.setVariable('DELVfModVol_CompleteMsoProcessRequest', null)
81                 execution.setVariable('DELVfModVol_WorkflowException', null)
82                 execution.setVariable('DELVfModVol_TransactionSuccessIndicator', false)
83                 execution.setVariable("DELVfModVol_isErrorMessageException", false)
84                 execution.setVariable('DELVfModVol_syncResponseSent', false)
85         }
86
87         /**
88          * Perform initial processing, such as request validation, initialization of variables, etc.
89          * * @param execution
90          */
91         public void preProcessRequest (DelegateExecution execution) {
92                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
93                 preProcessRequest(execution, isDebugEnabled)
94         }
95
96         /**
97          * This method is executed during the preProcessRequest task of the <class>DeleteVfModuleVolume.bpmn</class> process.
98          * @param execution
99          */
100         public void preProcessRequest (DelegateExecution execution, isDebugLogEnabled) {
101
102                 InitializeProcessVariables(execution)
103
104                 String createVolumeIncoming = validateRequest(execution)
105
106                 // check if request is xml or json
107                 try {
108                         def jsonSlurper = new JsonSlurper()
109                         Map reqMap = jsonSlurper.parseText(createVolumeIncoming)
110                         logger.debug(" Request is in JSON format.")
111
112                         def serviceInstanceId = execution.getVariable('serviceInstanceId')
113                         def volumeGroupId = execution.getVariable('volumeGroupId')
114                         def vidUtils = new VidUtils(this)
115                         createVolumeIncoming = vidUtils.createXmlVolumeRequest(reqMap, 'DELETE_VF_MODULE_VOL', serviceInstanceId, volumeGroupId)
116                         execution.setVariable("DELVfModVol_isVidRequest", true)
117                 }
118                 catch(groovy.json.JsonException je) {
119                         logger.debug(" Request is in XML format.")
120                         // assume request is in XML format - proceed as usual to process XML request
121                 }
122
123                 String request = utils.getNodeXml(createVolumeIncoming, "volume-request").drop(38).trim().replace("tag0:","").replace(":tag0","")
124                 execution.setVariable("DELVfModVol_volumeRequest", request)
125
126                 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
127                 execution.setVariable('DELVfModVol_requestInfo', requestInfo)
128                 String requestId = execution.getVariable("mso-request-id")
129                 if (requestId == null || requestId == "") {
130                         requestId = getRequiredNodeText(execution, requestInfo, 'request-id')
131                 }
132                 execution.setVariable('DELVfModVol_requestId', requestId)
133                 execution.setVariable('DELVfModVol_source', getNodeTextForce(requestInfo, 'source'))
134
135                 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
136                 execution.setVariable('DELVfModVol_volumeInputs', volumeInputs)
137                 execution.setVariable('DELVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
138                 execution.setVariable('DELVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
139                 execution.setVariable('DELVfModVol_serviceId', utils.getNodeText(volumeInputs, 'service-id'))
140                 execution.setVariable('DELVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
141                 execution.setVariable('DELVfModVol_messageId', UUID.randomUUID().toString())
142                 execution.setVariable('DELVfModVol_volumeOutputs', utils.getNodeXml(request, 'volume-outputs', false))
143                 execution.setVariable('DELVfModVol_volumeParams', utils.getNodeXml(request, 'volume-params'))
144                 execution.setVariable('DELVfModVol_cloudRegion', utils.getNodeText(request, 'aic-cloud-region'))
145                 execution.setVariable('DELVfModVol_cloudOwner', utils.getNodeText(request, 'cloud-owner'))
146
147                 setBasicDBAuthHeader(execution, isDebugLogEnabled)
148
149                 logger.debug('Request: ' + createVolumeIncoming)
150         }
151
152         public void sendSyncResponse (DelegateExecution execution, isDebugEnabled) {
153
154                 String volumeRequest = execution.getVariable("DELVfModVol_volumeRequest")
155                 logger.debug(" DELVfModVol_volumeRequest - " + "\n" + volumeRequest)
156                 // RESTResponse (for API Handler (APIH) Reply Task)
157                 String deleteVolumeRequest =
158                                 """<rest:RESTResponse xmlns:rest="http://schemas.activebpel.org/REST/2007/12/01/aeREST.xsd" statusCode="200">
159                 <rest:payload xmlns:rest="http://schemas.activebpel.org/REST/2007/12/01/aeREST.xsd"
160                           contentType="text/xml">
161                                 ${volumeRequest}
162                 </rest:payload>
163                        </rest:RESTResponse>""".trim()
164
165                 def isVidRequest = execution.getVariable('DELVfModVol_isVidRequest')
166                 def syncResponse = ''
167
168                 if(isVidRequest) {
169                         def serviceInstanceId = execution.getVariable('serviceInstanceId')
170                         def volumeGroupId = execution.getVariable('volumeGroupId')
171                         def requestId = execution.getVariable('DELVfModVol_requestId')
172                         syncResponse = """{"requestReferences":{"instanceId":"${volumeGroupId}","requestId":"${requestId}"}}""".trim()
173                 }
174                 else {
175                         syncResponse = utils.formatXml(deleteVolumeRequest)
176                 }
177
178                 execution.setVariable('DELVfModVol_syncResponseSent', true)
179
180                 sendWorkflowResponse(execution, 200, syncResponse)
181         }
182
183
184         public void sendSyncError (DelegateExecution execution, isDebugEnabled) {
185                 WorkflowException we = execution.getVariable('WorkflowException')
186                 def errorCode = we?.getErrorCode()
187                 def errorMessage = we?.getErrorMessage()
188                 //default to 400 since only invalid request will trigger this method
189                 sendWorkflowResponse(execution, 400, errorMessage)
190         }
191
192
193         public void callRESTQueryAAICloudRegion (DelegateExecution execution, isDebugEnabled) {
194
195                 String cloudRegion = execution.getVariable('DELVfModVol_cloudRegion')
196
197                 AaiUtil aaiUtil = new AaiUtil(this)
198
199                 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.CLOUD_REGION, Defaults.CLOUD_OWNER.toString(), cloudRegion)
200                 def queryCloudRegionRequest = aaiUtil.createAaiUri(uri)
201
202                 execution.setVariable("DELVfModVol_queryCloudRegionRequest", queryCloudRegionRequest)
203
204                 cloudRegion = aaiUtil.getAAICloudReqion(execution,  queryCloudRegionRequest, "PO", cloudRegion)
205
206                 ExceptionUtil exceptionUtil = new ExceptionUtil()
207
208                 if ((cloudRegion != "ERROR")) {
209                         if(execution.getVariable("DELVfModVol_queryCloudRegionReturnCode") == "404"){
210                                 execution.setVariable("DELVfModVol_aicCloudRegion", "AAIAIC25")
211                         }else{
212                                 execution.setVariable("DELVfModVol_aicCloudRegion", cloudRegion)
213                         }
214                         execution.setVariable("DELVfModVol_cloudRegion", cloudRegion)
215                         execution.setVariable("DELVfModVol_isCloudRegionGood", true)
216
217                 } else {
218                         logger.debug("AAI Query Cloud Region Unsuccessful.")
219                         execution.setVariable("DELVfModVol_isCloudRegionGood", false)
220                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "AAI Query Cloud Region Unsuccessful. Return Code: " + execution.getVariable("DELVfModVol_queryCloudRegionReturnCode"))
221                 }
222
223                 logger.debug(" is Cloud Region Good: " + execution.getVariable("DELVfModVol_isCloudRegionGood"))
224         }
225
226         /**
227          * Query volume group by id
228          * @param execution
229          */
230         public void queryAAIForVolumeGroup(DelegateExecution execution, isDebugLogEnabled) {
231
232                 ExceptionUtil exceptionUtil = new ExceptionUtil()
233
234                 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
235                 if(volumeGroupId == null) {
236                         exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'volume-group-id is not provided in the request')
237                         throw new Exception('volume-group-id is not provided in the request')
238                 }
239                 String cloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
240
241         try {
242             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), cloudRegion, volumeGroupId)
243             AAIResultWrapper volumeGroupWrapper = getAAIClient().get(uri)
244
245             if (!volumeGroupWrapper.isEmpty()) {
246                 Optional<VolumeGroup> volumeGroupOp = volumeGroupWrapper.asBean(VolumeGroup.class)
247                 execution.setVariable("DELVfModVol_queryAAIVolGrpResponse", volumeGroupOp.get())
248                 def heatStackId = volumeGroupOp.get().getHeatStackId() ?: ""
249                 execution.setVariable('DELVfModVol_volumeGroupHeatStackId', heatStackId)
250
251                 if ( volumeGroupWrapper.getRelationships().isPresent() && !volumeGroupWrapper.getRelationships().get().getRelatedAAIUris(AAIObjectType.VF_MODULE).isEmpty()) {
252                     logger.debug('Volume Group ' + volumeGroupId + ' currently in use')
253                     exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} currently in use - found vf-module relationship.")
254                 }
255
256                 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroupWrapper)
257                 if (volumeGroupTenantId == null) {
258                     logger.debug("Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
259                     exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
260                 }
261
262                 execution.setVariable('DELVfModVol_volumeGroupTenantId', volumeGroupTenantId)
263                 logger.debug('Received Tenant Id ' + volumeGroupTenantId + ' from AAI for Volume Group with Volume Group Id ' + volumeGroupId)
264             } else {
265                 logger.debug("Volume Group ${volumeGroupId} not found in AAI")
266                 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} not found in AAI. Response code: 404")
267             }
268         }catch (BpmnError e){
269             throw e
270         }catch (Exception e){
271             WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(e.getMessage(), execution)
272             throw new BpmnError("MSOWorkflowException")
273         }
274         }
275
276         /**
277          * Extract the Tenant Id from the Volume Group information returned by AAI.
278          *
279          * @param volumeGroupXml Volume Group XML returned by AAI.
280          * @return the Tenant Id extracted from the Volume Group information. 'null' is returned if
281          * the Tenant Id is missing or could not otherwise be extracted.
282          */
283         private String getTenantIdFromVolumeGroup(AAIResultWrapper wrapper) {
284         if(wrapper.getRelationships().isPresent()) {
285             List<AAIResourceUri> tenantURIList = wrapper.getRelationships().get().getRelatedAAIUris(AAIObjectType.TENANT)
286             if(!tenantURIList.isEmpty()){
287                 return tenantURIList.get(0).getURIKeys().get("tenant-id")
288             }
289         }
290                 return null
291         }
292
293         private boolean hasVnfRelationship(String volumeGroupXml) {
294                 def Node volumeGroupNode = xmlParser.parseText(volumeGroupXml)
295                 def Node relationshipList = utils.getChildNode(volumeGroupNode, 'relationship-list')
296                 if (relationshipList != null) {
297                         def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
298                         for (Node relationship in relationships) {
299                                 def Node relatedTo = utils.getChildNode(relationship, 'related-to')
300                                 if ((relatedTo != null) && (relatedTo.text().equals('generic-vnf'))) {
301                                         def Node relatedLink = utils.getChildNode(relationship, 'related-link')
302                                         if (relatedLink !=null && relatedLink.text() != null){
303                                                 return true
304                                         }
305                                 }
306                         }
307                 }
308                 return false
309         }
310
311         public void prepareVnfAdapterDeleteRequest(DelegateExecution execution, isDebugLogEnabled) {
312                 def cloudRegion = execution.getVariable('DELVfModVol_cloudRegion')
313                 def cloudOwner = execution.getVariable('DELVfModVol_cloudOwner')
314                 def tenantId = execution.getVariable('DELVfModVol_tenantId')
315                 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
316                 def volumeGroupHeatStackId = execution.getVariable('DELVfModVol_volumeGroupHeatStackId')
317                 def requestId = execution.getVariable('DELVfModVol_requestId')
318                 def serviceId = execution.getVariable('DELVfModVol_serviceId')
319
320                 def messageId = execution.getVariable('DELVfModVol_messageId')
321                 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
322                 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host", execution)
323                 if ('true'.equals(useQualifiedHostName)) {
324                                 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
325                 }
326
327                 String vnfAdapterRestRequest = """
328                         <deleteVolumeGroupRequest>
329                                 <cloudSiteId>${MsoUtils.xmlEscape(cloudRegion)}</cloudSiteId>
330                                 <cloudOwner>${MsoUtils.xmlEscape(cloudOwner)}</cloudOwner>
331                                 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
332                                 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
333                                 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
334                                 <skipAAI>true</skipAAI>
335                             <msoRequest>
336                                 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
337                                 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
338                             </msoRequest>
339                             <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
340                             <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
341                         </deleteVolumeGroupRequest>
342                 """
343                 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
344                 execution.setVariable('DELVfModVol_deleteVnfARequest', vnfAdapterRestRequest)
345                 logger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
346         }
347
348
349         public void deleteVolGrpId(DelegateExecution execution, isDebugEnabled) {
350
351                 // get variables
352         VolumeGroup volumeGroup = execution.getVariable("DELVfModVol_queryAAIVolGrpResponse")
353                 String groupId = volumeGroup.getVolumeGroupId()
354                 String cloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
355
356         ExceptionUtil exceptionUtil = new ExceptionUtil()
357         try {
358             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), cloudRegion, groupId)
359             getAAIClient().delete(uri)
360             logger.debug("Volume group $groupId deleted.")
361         }catch(NotFoundException e){
362             exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume group $groupId not found for delete in AAI Response code: 404")
363         }catch(Exception e1){
364             WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(e1.getMessage(), execution)
365             throw new BpmnError("MSOWorkflowException")
366         }
367         }
368
369
370         public void prepareDBRequest (DelegateExecution execution, isDebugLogEnabled) {
371
372                 WorkflowException workflowExceptionObj = execution.getVariable("WorkflowException")
373                 ExceptionUtil exceptionUtil = new ExceptionUtil();
374                 def requestId = execution.getVariable('DELVfModVol_requestId')
375                 def volOutputs = execution.getVariable('DELVfModVol_volumeOutputs')
376                 def statusMessage = "VolumeGroup successfully deleted"
377                 def progress = "100"
378                 def requestStatus = "COMPLETE"
379
380                 if (workflowExceptionObj != null) {
381                         statusMessage = (workflowExceptionObj.getErrorMessage())
382                         execution.setVariable("DELVfModVol_WorkflowExceptionMessage", statusMessage)
383                         execution.setVariable("DELVfModVol_WorkflowExceptionCode", workflowExceptionObj.getErrorCode())
384                         requestStatus = "FAILURE"
385                         progress = ""
386                 }
387
388                 String updateInfraRequest = """
389                         <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
390                                         xmlns:req="http://org.onap.so/requestsdb">
391                                 <soapenv:Header/>
392                                 <soapenv:Body>
393                                         <req:updateInfraRequest>
394                                                 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
395                                                 <lastModifiedBy>BPMN</lastModifiedBy>
396                                                 <statusMessage>${MsoUtils.xmlEscape(statusMessage)}</statusMessage>
397                                                 <requestStatus>${MsoUtils.xmlEscape(requestStatus)}</requestStatus>
398                                                 <progress>${MsoUtils.xmlEscape(progress)}</progress>
399                                                 <vnfOutputs>${MsoUtils.xmlEscape(volOutputs)}</vnfOutputs>
400                                         </req:updateInfraRequest>
401                                 </soapenv:Body>
402                         </soapenv:Envelope>
403                 """
404
405                 updateInfraRequest = utils.formatXml(updateInfraRequest)
406                 execution.setVariable('DELVfModVol_updateInfraRequest', updateInfraRequest)
407                 logger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
408
409         }
410
411
412         public void prepareCompletionHandlerRequest (DelegateExecution execution, isDebugLogEnabled) {
413                 def requestId = execution.getVariable("mso-request-id")
414                 def source = execution.getVariable("DELVfModVol_source")
415
416                 String msoCompletionRequest =
417                         """<aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
418                                                         xmlns:ns="http://org.onap/so/request/types/v1">
419                                         <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
420                                                 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
421                                                 <action>DELETE</action>
422                                                 <source>${MsoUtils.xmlEscape(source)}</source>
423                                         </request-info>
424                                         <aetgt:status-message>Volume Group has been deleted successfully.</aetgt:status-message>
425                                         <aetgt:mso-bpel-name>BPMN VF Module Volume action: DELETE</aetgt:mso-bpel-name>
426                                 </aetgt:MsoCompletionRequest>"""
427
428                 String xmlMsoCompletionRequest = utils.formatXml(msoCompletionRequest)
429                 execution.setVariable('DELVfModVol_CompleteMsoProcessRequest', xmlMsoCompletionRequest)
430                 logger.debug(" Overall SUCCESS Response going to CompleteMsoProcess - " + "\n" + xmlMsoCompletionRequest)
431
432         }
433
434
435
436         public void prepareFalloutHandler (DelegateExecution execution) {
437
438                 execution.setVariable("DELVfModVol_Success", false)
439                 String requestId = execution.getVariable("DELVfModVol_requestId")
440                 String source = execution.getVariable("DELVfModVol_source")
441
442                 WorkflowException workflowExceptionObj = execution.getVariable("WorkflowException")
443                 def errorMessage = workflowExceptionObj.getErrorMessage()
444                 def errorCode =  workflowExceptionObj.getErrorCode()
445
446                 String falloutHandlerRequest =
447                     """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
448                                                              xmlns:ns="http://org.onap/so/request/types/v1"
449                                                              xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
450                                    <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
451                                       <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
452                                       <action>DELETE</action>
453                                       <source>${MsoUtils.xmlEscape(source)}</source>
454                                    </request-info>
455                                         <aetgt:WorkflowException>
456                                       <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
457                                       <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
458                                         </aetgt:WorkflowException>
459                                 </aetgt:FalloutHandlerRequest>"""
460
461                 // Format Response
462                 String xmlHandlerRequest = utils.formatXml(falloutHandlerRequest)
463                 logger.debug(xmlHandlerRequest)
464
465                 execution.setVariable("DELVfModVol_FalloutHandlerRequest", xmlHandlerRequest)
466                 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
467                                 "Overall Error Response going to FalloutHandler", "BPMN",
468                                 ErrorCode.UnknownError.getValue(), "\n" + xmlHandlerRequest);
469         }
470
471
472         /**
473          * Create a WorkflowException for the error case where the Tenant Id from
474          * AAI did not match the Tenant Id in the incoming request.
475          *
476          * @param execution The flow's execution instance.
477          */
478         public void handleTenantIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
479
480                 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
481                 def aicCloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
482                 def tenantId = execution.getVariable('DELVfModVol_tenantId')
483                 def volumeGroupTenantId = execution.getVariable('DELVfModVol_volumeGroupTenantId')
484
485                 def String errorMessage = 'TenantId ' + tenantId + ' in incoming request does not match Tenant Id ' + volumeGroupTenantId +
486                         ' retrieved from AAI for Volume Group Id ' + volumeGroupId
487                 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
488                                 "Error in DeleteVfModuleVolume: " + "\n" + errorMessage, "BPMN",
489                                 ErrorCode.UnknownError.getValue());
490
491                 ExceptionUtil exceptionUtil = new ExceptionUtil()
492                 exceptionUtil.buildWorkflowException(execution, 5000, errorMessage)
493
494         }
495
496 }