2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. 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=========================================================
21 package org.onap.so.bpmn.infrastructure.scripts
23 import org.apache.commons.collections.CollectionUtils
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.aai.domain.yang.VolumeGroup
27 import org.onap.so.bpmn.common.scripts.ExceptionUtil
28 import org.onap.so.bpmn.common.scripts.MsoUtils
29 import org.onap.so.bpmn.common.scripts.VfModuleBase
30 import org.onap.so.bpmn.core.UrnPropertiesReader
31 import org.onap.so.bpmn.core.WorkflowException
32 import org.onap.so.client.aai.AAIObjectType
33 import org.onap.so.client.aai.entities.AAIResultWrapper
34 import org.onap.so.client.aai.entities.Relationships
35 import org.onap.so.client.aai.entities.uri.AAIResourceUri
36 import org.onap.so.client.aai.entities.uri.AAIUriFactory
37 import org.onap.so.constants.Defaults
38 import org.onap.so.logger.MessageEnum
39 import org.onap.so.logger.MsoLogger
40 import static org.apache.commons.lang.StringUtils.isEmpty
42 class UpdateVfModuleVolume extends VfModuleBase {
43 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateVfModuleVolume.class)
45 ExceptionUtil exceptionUtil = new ExceptionUtil()
48 * Initialize the flow's variables.
50 * @param execution The flow's execution instance.
52 private void initProcessVariables(DelegateExecution execution) {
53 execution.setVariable('prefix', 'UPDVfModVol_')
54 execution.setVariable('UPDVfModVol_Request', null)
55 execution.setVariable('UPDVfModVol_requestInfo', null)
56 execution.setVariable('UPDVfModVol_requestId', null)
57 execution.setVariable('UPDVfModVol_source', null)
58 execution.setVariable('UPDVfModVol_volumeInputs', null)
59 execution.setVariable('UPDVfModVol_volumeGroupId', null)
60 execution.setVariable('UPDVfModVol_vnfType', null)
61 execution.setVariable('UPDVfModVol_serviceId', null)
62 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
63 execution.setVariable('UPDVfModVol_tenantId', null)
64 execution.setVariable('UPDVfModVol_volumeParams', null)
65 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
66 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
67 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
71 * Check for missing elements in the received request.
73 * @param execution The flow's execution instance.
76 public void preProcessRequest(DelegateExecution execution) {
77 def method = getClass().getSimpleName() + '.preProcessRequest(' +
78 'execution=' + execution.getId() +
81 msoLogger.trace('Entered ' + method)
84 initProcessVariables(execution)
85 String request = validateRequest(execution)
87 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
88 execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
89 execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
90 execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
92 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
93 execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
94 execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
95 execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
96 execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
97 execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
98 execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
100 def volumeParams = utils.getNodeXml(request, 'volume-params')
101 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
103 msoLogger.trace('Exited ' + method)
104 msoLogger.debug("UpdateVfModuleVolume request: " + request)
105 } catch (BpmnError bpmnError) {
107 } catch (Exception e) {
108 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
109 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
114 * Prepare and send the synchronous response.
116 * @param execution The flow's execution instance.
118 public void sendSynchResponse(DelegateExecution execution) {
119 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
120 'execution=' + execution.getId() +
123 msoLogger.trace('Entered ' + method)
126 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
127 def requestId = execution.getVariable('UPDVfModVol_requestId')
128 def source = execution.getVariable('UPDVfModVol_source')
129 def progress = getNodeTextForce(requestInfo, 'progress')
130 if (progress.isEmpty()) {
133 def startTime = getNodeTextForce(requestInfo, 'start-time')
134 if (startTime.isEmpty()) {
135 startTime = System.currentTimeMillis()
137 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
139 String synchResponse = """
140 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
142 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
143 <action>UPDATE_VF_MODULE_VOL</action>
144 <request-status>IN_PROGRESS</request-status>
145 <progress>${MsoUtils.xmlEscape(progress)}</progress>
146 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
147 <source>${MsoUtils.xmlEscape(source)}</source>
153 synchResponse = utils.formatXml(synchResponse)
154 sendWorkflowResponse(execution, 200, synchResponse)
155 msoLogger.debug("UpdateVfModuleVolume Synch Response: " + synchResponse)
156 } catch (BpmnError e) {
158 } catch (Exception e) {
159 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
160 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
165 * Prepare a Request for querying AAI for Volume Group information using the
166 * Volume Group Id and Aic Cloud Region.
168 * @param execution The flow's execution instance.
170 public void queryAAIForVolumeGroup(DelegateExecution execution) {
171 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
172 'execution=' + execution.getId() +
175 msoLogger.trace('Entered ' + method)
178 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
179 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
180 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(),aicCloudRegion,volumeGroupId)
181 AAIResultWrapper wrapper = getAAIClient().get(uri)
182 Optional<VolumeGroup> volumeGroup = wrapper.asBean(VolumeGroup.class)
183 if(volumeGroup.isPresent()){
184 def heatStackId = volumeGroup.get().getHeatStackId()
185 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
186 Optional<Relationships> relationships = wrapper.getRelationships()
187 if(relationships.isPresent()){
188 List<AAIResourceUri> resourceUriList = relationships.get().getRelatedAAIUris(AAIObjectType.TENANT)
189 if(CollectionUtils.isNotEmpty(resourceUriList)){
190 AAIResourceUri tenantUri = resourceUriList.get(0)
191 String volumeGroupTenantId = tenantUri.getURIKeys().get("tenant-id")
192 if( isEmpty(volumeGroupTenantId)){
193 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
195 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
196 msoLogger.debug("Received Tenant Id: " + volumeGroupTenantId + "from AAI for Volume Group with Volume Group Id: " + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
198 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
202 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Volume Group" + volumeGroupId + " not found at AAI")
204 msoLogger.trace('Exited ' + method)
205 } catch (BpmnError e) {
207 } catch (Exception e) {
208 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
209 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
214 * Prepare a Request for invoking the VnfAdapterRest subflow to do
215 * a Volume Group update.
217 * @param execution The flow's execution instance.
219 public void prepVnfAdapterRest(DelegateExecution execution) {
220 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
221 'execution=' + execution.getId() +
224 msoLogger.trace('Entered ' + method)
227 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
228 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
229 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
230 def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
231 def vnfType = execution.getVariable('UPDVfModVol_vnfType')
233 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
234 def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
236 def requestId = execution.getVariable('UPDVfModVol_requestId')
237 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
239 def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
240 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
241 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution)
242 if ('true'.equals(useQualifiedHostName)) {
243 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
246 String vnfAdapterRestRequest = """
247 <updateVolumeGroupRequest>
248 <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
249 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
250 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
251 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
252 <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
253 <vnfVersion></vnfVersion>
254 <vfModuleType></vfModuleType>
258 <skipAAI>true</skipAAI>
260 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
261 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
263 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
264 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
265 </updateVolumeGroupRequest>
267 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
268 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
269 msoLogger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
271 msoLogger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest)
272 msoLogger.trace('Exited ' + method)
273 } catch (BpmnError e) {
275 } catch (Exception e) {
276 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
277 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
282 * Prepare a Request for updating the DB for this Infra request.
284 * @param execution The flow's execution instance.
286 public void prepDbInfraDbRequest(DelegateExecution execution) {
287 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
288 'execution=' + execution.getId() +
291 msoLogger.trace('Entered ' + method)
294 def requestId = execution.getVariable('UPDVfMod_requestId')
296 String updateInfraRequest = """
297 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
298 xmlns:req="http://org.onap.so/requestsdb">
301 <req:updateInfraRequest>
302 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
303 <lastModifiedBy>BPEL</lastModifiedBy>
304 <requestStatus>COMPLETE</requestStatus>
305 <progress>100</progress>
306 </req:updateInfraRequest>
311 updateInfraRequest = utils.formatXml(updateInfraRequest)
312 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
313 msoLogger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
315 msoLogger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest)
316 msoLogger.trace('Exited ' + method)
317 } catch (BpmnError e) {
319 } catch (Exception e) {
320 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
321 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
326 * Build a "CompletionHandler" request.
328 * @param execution The flow's execution instance.
330 public void prepCompletionHandlerRequest(DelegateExecution execution) {
331 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
332 'execution=' + execution.getId() +
335 msoLogger.trace('Entered ' + method)
338 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
341 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
342 xmlns:reqtype="http://org.onap/so/request/types/v1">
344 <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
345 </sdncadapterworkflow:MsoCompletionRequest>
348 content = utils.formatXml(content)
349 msoLogger.debug('Request for Completion Handler:\n' + content)
350 msoLogger.debug("UpdateVfModuleVolume Completion Handler request: " + content)
351 execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
353 msoLogger.trace('Exited ' + method)
354 } catch (BpmnError e) {
356 } catch (Exception e) {
357 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
358 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
363 * Build a "FalloutHandler" request.
365 * @param execution The flow's execution instance.
367 public void prepFalloutHandler(DelegateExecution execution) {
368 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
369 'execution=' + execution.getId() +
372 msoLogger.trace('Entered ' + method)
375 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
377 def WorkflowException workflowException = execution.getVariable("WorkflowException")
378 def errorResponseCode = workflowException.getErrorCode()
379 def errorResponseMsg = workflowException.getErrorMessage()
380 def encErrorResponseMsg = ""
381 if (errorResponseMsg != null) {
382 encErrorResponseMsg = errorResponseMsg
386 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
387 xmlns:reqtype="http://org.onap/so/request/types/v1"
388 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
389 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
391 <sdncadapterworkflow:WorkflowException>
392 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
393 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
394 </sdncadapterworkflow:WorkflowException>
395 </sdncadapterworkflow:FalloutHandlerRequest>
397 content = utils.formatXml(content)
398 msoLogger.debug('Request for Fallout Handler:\n' + content)
399 msoLogger.debug("UpdateVfModuleVolume Fallout request: " + content)
400 execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
402 msoLogger.trace('Exited ' + method)
403 } catch (BpmnError e) {
405 } catch (Exception e) {
406 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e)
407 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
412 * Create a WorkflowException for the error case where the Tenant Id from
413 * AAI did not match the Tenant Id in the incoming request.
415 * @param execution The flow's execution instance.
417 public void handleTenantIdMismatch(DelegateExecution execution) {
418 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
419 'execution=' + execution.getId() +
422 msoLogger.trace('Entered ' + method)
424 String processKey = getProcessKey(execution)
425 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
426 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
427 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
428 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
430 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
431 '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
433 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Error in UpdateVfModuleVol: ' + errorMessage, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception")
435 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage)
436 execution.setVariable("WorkflowException", exception)
438 msoLogger.trace('Exited ' + method)
439 msoLogger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)