2 * ============LICENSE_START=======================================================
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
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=========================================================
23 package org.onap.so.bpmn.infrastructure.scripts;
25 import org.apache.commons.lang3.*
26 import org.camunda.bpm.engine.delegate.BpmnError
27 import org.camunda.bpm.engine.delegate.DelegateExecution
28 import org.onap.aai.domain.yang.VolumeGroup
29 import org.onap.so.bpmn.common.scripts.AaiUtil;
30 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor;
31 import org.onap.so.bpmn.common.scripts.ExceptionUtil;
32 import org.onap.so.bpmn.common.scripts.MsoUtils
33 import org.onap.so.bpmn.common.scripts.VidUtils;
34 import org.onap.so.bpmn.core.UrnPropertiesReader
35 import org.onap.so.bpmn.core.WorkflowException
36 import org.onap.so.client.aai.AAIObjectType
37 import org.onap.so.client.aai.entities.AAIResultWrapper
38 import org.onap.so.client.aai.entities.Relationships
39 import org.onap.so.client.aai.entities.uri.AAIResourceUri
40 import org.onap.so.client.aai.entities.uri.AAIUriFactory
41 import org.onap.so.constants.Defaults
42 import org.onap.so.logger.MessageEnum
43 import org.onap.so.logger.MsoLogger
44 import org.slf4j.Logger
45 import org.slf4j.LoggerFactory
46 import org.springframework.web.util.UriUtils
49 import groovy.json.JsonSlurper
51 import javax.ws.rs.NotFoundException
54 * This groovy class supports the <class>DeleteVfModuleVolume.bpmn</class> process.
56 public class DeleteVfModuleVolumeInfraV1 extends AbstractServiceTaskProcessor {
57 private static final Logger logger = LoggerFactory.getLogger( DeleteVfModuleVolumeInfraV1.class);
59 private XmlParser xmlParser = new XmlParser()
61 * This method is executed during the preProcessRequest task of the <class>DeleteVfModuleVolume.bpmn</class> process.
64 public InitializeProcessVariables(DelegateExecution execution){
65 execution.setVariable('prefix', 'DELVfModVol_')
66 execution.setVariable("DELVfModVol_volumeRequest", null)
67 execution.setVariable('DELVfModVol_requestInfo', null)
68 execution.setVariable('DELVfModVol_requestId', null)
69 execution.setVariable('DELVfModVol_source', null)
70 execution.setVariable('DELVfModVol_volumeInputs', null)
71 execution.setVariable('DELVfModVol_volumeOutputs', null)
72 execution.setVariable('DELVfModVol_volumeGroupId', null)
73 execution.setVariable('DELVfModVol_vnfType', null)
74 execution.setVariable('DELVfModVol_serviceId', null)
75 execution.setVariable('DELVfModVol_cloudRegion', null)
76 execution.setVariable('DELVfModVol_tenantId', null)
77 execution.setVariable('DELVfModVol_volumeParams', null)
78 execution.setVariable('DELVfModVol_volumeGroupHeatStackId', null)
79 execution.setVariable('DELVfModVol_volumeGroupTenantId', null)
80 execution.setVariable("DELVfModVol_queryAAIVolGrpResponse", null)
81 execution.setVariable('DELVfModVol_messageId', null)
82 execution.setVariable('DELVfModVol_deleteVnfARequest', null)
83 execution.setVariable('DELVfModVol_updateInfraRequest', null)
84 execution.setVariable('DELVfModVol_CompleteMsoProcessRequest', null)
85 execution.setVariable('DELVfModVol_WorkflowException', null)
86 execution.setVariable('DELVfModVol_TransactionSuccessIndicator', false)
87 execution.setVariable("DELVfModVol_isErrorMessageException", false)
88 execution.setVariable('DELVfModVol_syncResponseSent', false)
92 * Perform initial processing, such as request validation, initialization of variables, etc.
95 public void preProcessRequest (DelegateExecution execution) {
96 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
97 preProcessRequest(execution, isDebugEnabled)
101 * This method is executed during the preProcessRequest task of the <class>DeleteVfModuleVolume.bpmn</class> process.
104 public void preProcessRequest (DelegateExecution execution, isDebugLogEnabled) {
106 InitializeProcessVariables(execution)
108 String createVolumeIncoming = validateRequest(execution)
110 // check if request is xml or json
112 def jsonSlurper = new JsonSlurper()
113 Map reqMap = jsonSlurper.parseText(createVolumeIncoming)
114 logger.debug(" Request is in JSON format.")
116 def serviceInstanceId = execution.getVariable('serviceInstanceId')
117 def volumeGroupId = execution.getVariable('volumeGroupId')
118 def vidUtils = new VidUtils(this)
119 createVolumeIncoming = vidUtils.createXmlVolumeRequest(reqMap, 'DELETE_VF_MODULE_VOL', serviceInstanceId, volumeGroupId)
120 execution.setVariable("DELVfModVol_isVidRequest", true)
122 catch(groovy.json.JsonException je) {
123 logger.debug(" Request is in XML format.")
124 // assume request is in XML format - proceed as usual to process XML request
127 String request = utils.getNodeXml(createVolumeIncoming, "volume-request").drop(38).trim().replace("tag0:","").replace(":tag0","")
128 execution.setVariable("DELVfModVol_volumeRequest", request)
130 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
131 execution.setVariable('DELVfModVol_requestInfo', requestInfo)
132 String requestId = execution.getVariable("mso-request-id")
133 if (requestId == null || requestId == "") {
134 requestId = getRequiredNodeText(execution, requestInfo, 'request-id')
136 execution.setVariable('DELVfModVol_requestId', requestId)
137 execution.setVariable('DELVfModVol_source', getNodeTextForce(requestInfo, 'source'))
139 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
140 execution.setVariable('DELVfModVol_volumeInputs', volumeInputs)
141 execution.setVariable('DELVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
142 execution.setVariable('DELVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
143 execution.setVariable('DELVfModVol_serviceId', utils.getNodeText(volumeInputs, 'service-id'))
144 execution.setVariable('DELVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
145 execution.setVariable('DELVfModVol_messageId', UUID.randomUUID().toString())
146 execution.setVariable('DELVfModVol_volumeOutputs', utils.getNodeXml(request, 'volume-outputs', false))
147 execution.setVariable('DELVfModVol_volumeParams', utils.getNodeXml(request, 'volume-params'))
148 execution.setVariable('DELVfModVol_cloudRegion', utils.getNodeText(request, 'aic-cloud-region'))
150 setBasicDBAuthHeader(execution, isDebugLogEnabled)
152 logger.debug('Request: ' + createVolumeIncoming)
155 public void sendSyncResponse (DelegateExecution execution, isDebugEnabled) {
157 String volumeRequest = execution.getVariable("DELVfModVol_volumeRequest")
158 logger.debug(" DELVfModVol_volumeRequest - " + "\n" + volumeRequest)
159 // RESTResponse (for API Handler (APIH) Reply Task)
160 String deleteVolumeRequest =
161 """<rest:RESTResponse xmlns:rest="http://schemas.activebpel.org/REST/2007/12/01/aeREST.xsd" statusCode="200">
162 <rest:payload xmlns:rest="http://schemas.activebpel.org/REST/2007/12/01/aeREST.xsd"
163 contentType="text/xml">
166 </rest:RESTResponse>""".trim()
168 def isVidRequest = execution.getVariable('DELVfModVol_isVidRequest')
169 def syncResponse = ''
172 def serviceInstanceId = execution.getVariable('serviceInstanceId')
173 def volumeGroupId = execution.getVariable('volumeGroupId')
174 def requestId = execution.getVariable('DELVfModVol_requestId')
175 syncResponse = """{"requestReferences":{"instanceId":"${volumeGroupId}","requestId":"${requestId}"}}""".trim()
178 syncResponse = utils.formatXml(deleteVolumeRequest)
181 execution.setVariable('DELVfModVol_syncResponseSent', true)
183 sendWorkflowResponse(execution, 200, syncResponse)
187 public void sendSyncError (DelegateExecution execution, isDebugEnabled) {
188 WorkflowException we = execution.getVariable('WorkflowException')
189 def errorCode = we?.getErrorCode()
190 def errorMessage = we?.getErrorMessage()
191 //default to 400 since only invalid request will trigger this method
192 sendWorkflowResponse(execution, 400, errorMessage)
196 public void callRESTQueryAAICloudRegion (DelegateExecution execution, isDebugEnabled) {
198 String cloudRegion = execution.getVariable('DELVfModVol_cloudRegion')
200 AaiUtil aaiUtil = new AaiUtil(this)
202 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.CLOUD_REGION, Defaults.CLOUD_OWNER.toString(), cloudRegion)
203 def queryCloudRegionRequest = aaiUtil.createAaiUri(uri)
205 execution.setVariable("DELVfModVol_queryCloudRegionRequest", queryCloudRegionRequest)
207 cloudRegion = aaiUtil.getAAICloudReqion(execution, queryCloudRegionRequest, "PO", cloudRegion)
209 ExceptionUtil exceptionUtil = new ExceptionUtil()
211 if ((cloudRegion != "ERROR")) {
212 if(execution.getVariable("DELVfModVol_queryCloudRegionReturnCode") == "404"){
213 execution.setVariable("DELVfModVol_aicCloudRegion", "AAIAIC25")
215 execution.setVariable("DELVfModVol_aicCloudRegion", cloudRegion)
217 execution.setVariable("DELVfModVol_cloudRegion", cloudRegion)
218 execution.setVariable("DELVfModVol_isCloudRegionGood", true)
221 logger.debug("AAI Query Cloud Region Unsuccessful.")
222 execution.setVariable("DELVfModVol_isCloudRegionGood", false)
223 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "AAI Query Cloud Region Unsuccessful. Return Code: " + execution.getVariable("DELVfModVol_queryCloudRegionReturnCode"))
226 logger.debug(" is Cloud Region Good: " + execution.getVariable("DELVfModVol_isCloudRegionGood"))
230 * Query volume group by id
233 public void queryAAIForVolumeGroup(DelegateExecution execution, isDebugLogEnabled) {
235 ExceptionUtil exceptionUtil = new ExceptionUtil()
237 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
238 if(volumeGroupId == null) {
239 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'volume-group-id is not provided in the request')
240 throw new Exception('volume-group-id is not provided in the request')
242 String cloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
245 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), cloudRegion, volumeGroupId)
246 AAIResultWrapper volumeGroupWrapper = getAAIClient().get(uri)
248 if (!volumeGroupWrapper.isEmpty()) {
249 Optional<VolumeGroup> volumeGroupOp = volumeGroupWrapper.asBean(VolumeGroup.class)
250 execution.setVariable("DELVfModVol_queryAAIVolGrpResponse", volumeGroupOp.get())
251 def heatStackId = volumeGroupOp.get().getHeatStackId() ?: ""
252 execution.setVariable('DELVfModVol_volumeGroupHeatStackId', heatStackId)
254 if ( volumeGroupWrapper.getRelationships().isPresent() && !volumeGroupWrapper.getRelationships().get().getRelatedAAIUris(AAIObjectType.VF_MODULE).isEmpty()) {
255 logger.debug('Volume Group ' + volumeGroupId + ' currently in use')
256 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} currently in use - found vf-module relationship.")
259 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroupWrapper)
260 if (volumeGroupTenantId == null) {
261 logger.debug("Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
262 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
265 execution.setVariable('DELVfModVol_volumeGroupTenantId', volumeGroupTenantId)
266 logger.debug('Received Tenant Id ' + volumeGroupTenantId + ' from AAI for Volume Group with Volume Group Id ' + volumeGroupId)
268 logger.debug("Volume Group ${volumeGroupId} not found in AAI")
269 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} not found in AAI. Response code: 404")
271 }catch (BpmnError e){
273 }catch (Exception e){
274 WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(e.getMessage(), execution)
275 throw new BpmnError("MSOWorkflowException")
280 * Extract the Tenant Id from the Volume Group information returned by AAI.
282 * @param volumeGroupXml Volume Group XML returned by AAI.
283 * @return the Tenant Id extracted from the Volume Group information. 'null' is returned if
284 * the Tenant Id is missing or could not otherwise be extracted.
286 private String getTenantIdFromVolumeGroup(AAIResultWrapper wrapper) {
287 if(wrapper.getRelationships().isPresent()) {
288 List<AAIResourceUri> tenantURIList = wrapper.getRelationships().get().getRelatedAAIUris(AAIObjectType.TENANT)
289 if(!tenantURIList.isEmpty()){
290 return tenantURIList.get(0).getURIKeys().get("tenant-id")
296 private boolean hasVnfRelationship(String volumeGroupXml) {
297 def Node volumeGroupNode = xmlParser.parseText(volumeGroupXml)
298 def Node relationshipList = utils.getChildNode(volumeGroupNode, 'relationship-list')
299 if (relationshipList != null) {
300 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
301 for (Node relationship in relationships) {
302 def Node relatedTo = utils.getChildNode(relationship, 'related-to')
303 if ((relatedTo != null) && (relatedTo.text().equals('generic-vnf'))) {
304 def Node relatedLink = utils.getChildNode(relationship, 'related-link')
305 if (relatedLink !=null && relatedLink.text() != null){
314 public void prepareVnfAdapterDeleteRequest(DelegateExecution execution, isDebugLogEnabled) {
315 def cloudRegion = execution.getVariable('DELVfModVol_cloudRegion')
316 def tenantId = execution.getVariable('DELVfModVol_tenantId')
317 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
318 def volumeGroupHeatStackId = execution.getVariable('DELVfModVol_volumeGroupHeatStackId')
319 def requestId = execution.getVariable('DELVfModVol_requestId')
320 def serviceId = execution.getVariable('DELVfModVol_serviceId')
322 def messageId = execution.getVariable('DELVfModVol_messageId')
323 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
324 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host", execution)
325 if ('true'.equals(useQualifiedHostName)) {
326 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
329 String vnfAdapterRestRequest = """
330 <deleteVolumeGroupRequest>
331 <cloudSiteId>${MsoUtils.xmlEscape(cloudRegion)}</cloudSiteId>
332 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
333 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
334 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
335 <skipAAI>true</skipAAI>
337 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
338 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
340 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
341 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
342 </deleteVolumeGroupRequest>
344 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
345 execution.setVariable('DELVfModVol_deleteVnfARequest', vnfAdapterRestRequest)
346 logger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
350 public void deleteVolGrpId(DelegateExecution execution, isDebugEnabled) {
353 VolumeGroup volumeGroup = execution.getVariable("DELVfModVol_queryAAIVolGrpResponse")
354 String groupId = volumeGroup.getVolumeGroupId()
355 String cloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
357 ExceptionUtil exceptionUtil = new ExceptionUtil()
359 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), cloudRegion, groupId)
360 getAAIClient().delete(uri)
361 logger.debug("Volume group $groupId deleted.")
362 }catch(NotFoundException e){
363 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume group $groupId not found for delete in AAI Response code: 404")
364 }catch(Exception e1){
365 WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(e1.getMessage(), execution)
366 throw new BpmnError("MSOWorkflowException")
371 public void prepareDBRequest (DelegateExecution execution, isDebugLogEnabled) {
373 WorkflowException workflowExceptionObj = execution.getVariable("WorkflowException")
374 ExceptionUtil exceptionUtil = new ExceptionUtil();
375 def requestId = execution.getVariable('DELVfModVol_requestId')
376 def volOutputs = execution.getVariable('DELVfModVol_volumeOutputs')
377 def statusMessage = "VolumeGroup successfully deleted"
379 def requestStatus = "COMPLETE"
381 if (workflowExceptionObj != null) {
382 statusMessage = (workflowExceptionObj.getErrorMessage())
383 execution.setVariable("DELVfModVol_WorkflowExceptionMessage", statusMessage)
384 execution.setVariable("DELVfModVol_WorkflowExceptionCode", workflowExceptionObj.getErrorCode())
385 requestStatus = "FAILURE"
389 String updateInfraRequest = """
390 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
391 xmlns:req="http://org.onap.so/requestsdb">
394 <req:updateInfraRequest>
395 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
396 <lastModifiedBy>BPMN</lastModifiedBy>
397 <statusMessage>${MsoUtils.xmlEscape(statusMessage)}</statusMessage>
398 <requestStatus>${MsoUtils.xmlEscape(requestStatus)}</requestStatus>
399 <progress>${MsoUtils.xmlEscape(progress)}</progress>
400 <vnfOutputs>${MsoUtils.xmlEscape(volOutputs)}</vnfOutputs>
401 </req:updateInfraRequest>
406 updateInfraRequest = utils.formatXml(updateInfraRequest)
407 execution.setVariable('DELVfModVol_updateInfraRequest', updateInfraRequest)
408 logger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
413 public void prepareCompletionHandlerRequest (DelegateExecution execution, isDebugLogEnabled) {
414 def requestId = execution.getVariable("mso-request-id")
415 def source = execution.getVariable("DELVfModVol_source")
417 String msoCompletionRequest =
418 """<aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
419 xmlns:ns="http://org.onap/so/request/types/v1">
420 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
421 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
422 <action>DELETE</action>
423 <source>${MsoUtils.xmlEscape(source)}</source>
425 <aetgt:status-message>Volume Group has been deleted successfully.</aetgt:status-message>
426 <aetgt:mso-bpel-name>BPMN VF Module Volume action: DELETE</aetgt:mso-bpel-name>
427 </aetgt:MsoCompletionRequest>"""
429 String xmlMsoCompletionRequest = utils.formatXml(msoCompletionRequest)
430 execution.setVariable('DELVfModVol_CompleteMsoProcessRequest', xmlMsoCompletionRequest)
431 logger.debug(" Overall SUCCESS Response going to CompleteMsoProcess - " + "\n" + xmlMsoCompletionRequest)
437 public void prepareFalloutHandler (DelegateExecution execution) {
439 execution.setVariable("DELVfModVol_Success", false)
440 String requestId = execution.getVariable("DELVfModVol_requestId")
441 String source = execution.getVariable("DELVfModVol_source")
443 WorkflowException workflowExceptionObj = execution.getVariable("WorkflowException")
444 def errorMessage = workflowExceptionObj.getErrorMessage()
445 def errorCode = workflowExceptionObj.getErrorCode()
447 String falloutHandlerRequest =
448 """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
449 xmlns:ns="http://org.onap/so/request/types/v1"
450 xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
451 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
452 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
453 <action>DELETE</action>
454 <source>${MsoUtils.xmlEscape(source)}</source>
456 <aetgt:WorkflowException>
457 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
458 <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
459 </aetgt:WorkflowException>
460 </aetgt:FalloutHandlerRequest>"""
463 String xmlHandlerRequest = utils.formatXml(falloutHandlerRequest)
464 logger.debug(xmlHandlerRequest)
466 execution.setVariable("DELVfModVol_FalloutHandlerRequest", xmlHandlerRequest)
467 logger.error("{} {} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
468 "Overall Error Response going to FalloutHandler", "BPMN", MsoLogger.getServiceName(),
469 MsoLogger.ErrorCode.UnknownError.getValue(), "\n" + xmlHandlerRequest);
474 * Create a WorkflowException for the error case where the Tenant Id from
475 * AAI did not match the Tenant Id in the incoming request.
477 * @param execution The flow's execution instance.
479 public void handleTenantIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
481 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
482 def aicCloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
483 def tenantId = execution.getVariable('DELVfModVol_tenantId')
484 def volumeGroupTenantId = execution.getVariable('DELVfModVol_volumeGroupTenantId')
486 def String errorMessage = 'TenantId ' + tenantId + ' in incoming request does not match Tenant Id ' + volumeGroupTenantId +
487 ' retrieved from AAI for Volume Group Id ' + volumeGroupId
488 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
489 "Error in DeleteVfModuleVolume: " + "\n" + errorMessage, "BPMN",
490 MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError.getValue());
492 ExceptionUtil exceptionUtil = new ExceptionUtil()
493 exceptionUtil.buildWorkflowException(execution, 5000, errorMessage)