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.lang3.*
24 import org.camunda.bpm.engine.delegate.BpmnError
25 import org.camunda.bpm.engine.delegate.DelegateExecution
26 import org.onap.so.bpmn.common.scripts.AaiUtil
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.uri.AAIResourceUri
34 import org.onap.so.client.aai.entities.uri.AAIUriFactory
35 import org.onap.so.constants.Defaults
36 import org.onap.so.logger.MessageEnum
37 import org.onap.so.logger.MsoLogger
38 import org.onap.so.rest.APIResponse
40 class UpdateVfModuleVolume extends VfModuleBase {
41 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateVfModuleVolume.class);
43 ExceptionUtil exceptionUtil = new ExceptionUtil()
46 * Initialize the flow's variables.
48 * @param execution The flow's execution instance.
50 private void initProcessVariables(DelegateExecution execution) {
51 execution.setVariable('prefix', 'UPDVfModVol_')
52 execution.setVariable('UPDVfModVol_Request', null)
53 execution.setVariable('UPDVfModVol_requestInfo', null)
54 execution.setVariable('UPDVfModVol_requestId', null)
55 execution.setVariable('UPDVfModVol_source', null)
56 execution.setVariable('UPDVfModVol_volumeInputs', null)
57 execution.setVariable('UPDVfModVol_volumeGroupId', null)
58 execution.setVariable('UPDVfModVol_vnfType', null)
59 execution.setVariable('UPDVfModVol_serviceId', null)
60 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
61 execution.setVariable('UPDVfModVol_tenantId', null)
62 execution.setVariable('UPDVfModVol_volumeParams', null)
63 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
64 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
65 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
69 * Check for missing elements in the received request.
71 * @param execution The flow's execution instance.
74 public void preProcessRequest(DelegateExecution execution) {
75 def method = getClass().getSimpleName() + '.preProcessRequest(' +
76 'execution=' + execution.getId() +
79 msoLogger.trace('Entered ' + method)
82 initProcessVariables(execution)
83 String request = validateRequest(execution)
85 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
86 execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
87 execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
88 execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
90 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
91 execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
92 execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
93 execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
94 execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
95 execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
96 execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
98 def volumeParams = utils.getNodeXml(request, 'volume-params')
99 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
101 msoLogger.trace('Exited ' + method)
102 msoLogger.debug("UpdateVfModuleVolume request: " + request)
103 } catch (BpmnError bpmnError) {
105 } catch (Exception e) {
106 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
107 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
112 * Prepare and send the synchronous response.
114 * @param execution The flow's execution instance.
116 public void sendSynchResponse(DelegateExecution execution) {
117 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
118 'execution=' + execution.getId() +
121 msoLogger.trace('Entered ' + method)
124 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
125 def requestId = execution.getVariable('UPDVfModVol_requestId')
126 def source = execution.getVariable('UPDVfModVol_source')
127 def progress = getNodeTextForce(requestInfo, 'progress')
128 if (progress.isEmpty()) {
131 def startTime = getNodeTextForce(requestInfo, 'start-time')
132 if (startTime.isEmpty()) {
133 startTime = System.currentTimeMillis()
135 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
137 String synchResponse = """
138 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
140 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
141 <action>UPDATE_VF_MODULE_VOL</action>
142 <request-status>IN_PROGRESS</request-status>
143 <progress>${MsoUtils.xmlEscape(progress)}</progress>
144 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
145 <source>${MsoUtils.xmlEscape(source)}</source>
151 synchResponse = utils.formatXml(synchResponse)
152 sendWorkflowResponse(execution, 200, synchResponse)
153 msoLogger.debug("UpdateVfModuleVolume Synch Response: " + synchResponse)
154 } catch (BpmnError e) {
156 } catch (Exception e) {
157 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
158 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
163 * Prepare a Request for querying AAI for Volume Group information using the
164 * Volume Group Id and Aic Cloud Region.
166 * @param execution The flow's execution instance.
168 public void queryAAIForVolumeGroup(DelegateExecution execution) {
169 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
170 'execution=' + execution.getId() +
173 msoLogger.trace('Entered ' + method)
176 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
177 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
179 AaiUtil aaiUtil = new AaiUtil(this)
180 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), aicCloudRegion, volumeGroupId)
181 String endPoint = aaiUtil.createAaiUri(uri)
184 msoLogger.debug('Sending GET to AAI endpoint \'' + endPoint + '\'')
185 msoLogger.debug("UpdateVfModuleVolume sending GET for quering AAI endpoint: " + endPoint)
187 APIResponse response = aaiUtil.executeAAIGetCall(execution, endPoint)
188 def int statusCode = response.getStatusCode()
189 def responseData = response.getResponseBodyAsString()
190 msoLogger.debug('Response code:' + statusCode)
191 msoLogger.debug('Response:' + System.lineSeparator() + responseData)
192 msoLogger.debug("UpdateVfModuleVolume response data: " + responseData)
194 def volumeGroup = responseData
195 def heatStackId = getNodeTextForce(volumeGroup, 'heat-stack-id')
196 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
197 if ((statusCode == 200) || (statusCode == 204)) {
198 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroup)
199 if (volumeGroupTenantId == null) {
200 throw new Exception('Could not find Tenant Id element in Volume Group with Volume Group Id \'' + volumeGroupId + '\''
201 + '\', AIC Cloud Region \'' + aicCloudRegion + '\'')
203 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
204 msoLogger.debug('Received Tenant Id \'' + volumeGroupTenantId + '\' from AAI for Volume Group with Volume Group Id \'' + volumeGroupId + '\''
205 + '\', AIC Cloud Region \'' + aicCloudRegion + '\'')
206 } else if (statusCode == 404) {
207 throw new Exception('Volume Group \'' + volumeGroupId + '\' not found at AAI')
209 throw new Exception('Bad status code ' + statusCode + ' received from AAI; Response data: ' + responseData)
212 msoLogger.trace('Exited ' + method)
213 } catch (BpmnError e) {
215 } catch (Exception e) {
216 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
217 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
222 * Prepare a Request for invoking the VnfAdapterRest subflow to do
223 * a Volume Group update.
225 * @param execution The flow's execution instance.
227 public void prepVnfAdapterRest(DelegateExecution execution) {
228 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
229 'execution=' + execution.getId() +
232 msoLogger.trace('Entered ' + method)
235 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
236 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
237 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
238 def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
239 def vnfType = execution.getVariable('UPDVfModVol_vnfType')
241 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
242 def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
244 def requestId = execution.getVariable('UPDVfModVol_requestId')
245 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
247 def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
248 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
249 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution)
250 if ('true'.equals(useQualifiedHostName)) {
251 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
254 String vnfAdapterRestRequest = """
255 <updateVolumeGroupRequest>
256 <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
257 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
258 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
259 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
260 <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
261 <vnfVersion></vnfVersion>
262 <vfModuleType></vfModuleType>
266 <skipAAI>true</skipAAI>
268 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
269 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
271 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
272 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
273 </updateVolumeGroupRequest>
275 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
276 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
277 msoLogger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
279 msoLogger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest)
280 msoLogger.trace('Exited ' + method)
281 } catch (BpmnError e) {
283 } catch (Exception e) {
284 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
285 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
290 * Prepare a Request for updating the DB for this Infra request.
292 * @param execution The flow's execution instance.
294 public void prepDbInfraDbRequest(DelegateExecution execution) {
295 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
296 'execution=' + execution.getId() +
299 msoLogger.trace('Entered ' + method)
302 def requestId = execution.getVariable('UPDVfMod_requestId')
304 String updateInfraRequest = """
305 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
306 xmlns:req="http://org.onap.so/requestsdb">
309 <req:updateInfraRequest>
310 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
311 <lastModifiedBy>BPEL</lastModifiedBy>
312 <requestStatus>COMPLETE</requestStatus>
313 <progress>100</progress>
314 </req:updateInfraRequest>
319 updateInfraRequest = utils.formatXml(updateInfraRequest)
320 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
321 msoLogger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
323 msoLogger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest)
324 msoLogger.trace('Exited ' + method)
325 } catch (BpmnError e) {
327 } catch (Exception e) {
328 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
329 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
334 * Build a "CompletionHandler" request.
336 * @param execution The flow's execution instance.
338 public void prepCompletionHandlerRequest(DelegateExecution execution) {
339 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
340 'execution=' + execution.getId() +
343 msoLogger.trace('Entered ' + method)
346 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
349 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
350 xmlns:reqtype="http://org.onap/so/request/types/v1">
352 <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
353 </sdncadapterworkflow:MsoCompletionRequest>
356 content = utils.formatXml(content)
357 msoLogger.debug('Request for Completion Handler:\n' + content)
358 msoLogger.debug("UpdateVfModuleVolume Completion Handler request: " + content)
359 execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
361 msoLogger.trace('Exited ' + method)
362 } catch (BpmnError e) {
364 } catch (Exception e) {
365 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
366 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
371 * Build a "FalloutHandler" request.
373 * @param execution The flow's execution instance.
375 public void prepFalloutHandler(DelegateExecution execution) {
376 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
377 'execution=' + execution.getId() +
380 msoLogger.trace('Entered ' + method)
383 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
385 def WorkflowException workflowException = execution.getVariable("WorkflowException")
386 def errorResponseCode = workflowException.getErrorCode()
387 def errorResponseMsg = workflowException.getErrorMessage()
388 def encErrorResponseMsg = ""
389 if (errorResponseMsg != null) {
390 encErrorResponseMsg = errorResponseMsg
394 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
395 xmlns:reqtype="http://org.onap/so/request/types/v1"
396 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
397 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
399 <sdncadapterworkflow:WorkflowException>
400 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
401 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
402 </sdncadapterworkflow:WorkflowException>
403 </sdncadapterworkflow:FalloutHandlerRequest>
405 content = utils.formatXml(content)
406 msoLogger.debug('Request for Fallout Handler:\n' + content)
407 msoLogger.debug("UpdateVfModuleVolume Fallout request: " + content)
408 execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
410 msoLogger.trace('Exited ' + method)
411 } catch (BpmnError e) {
413 } catch (Exception e) {
414 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
415 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
420 * Create a WorkflowException for the error case where the Tenant Id from
421 * AAI did not match the Tenant Id in the incoming request.
423 * @param execution The flow's execution instance.
425 public void handleTenantIdMismatch(DelegateExecution execution) {
426 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
427 'execution=' + execution.getId() +
430 msoLogger.trace('Entered ' + method)
432 String processKey = getProcessKey(execution);
433 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
434 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
435 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
436 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
438 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
439 '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
441 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Error in UpdateVfModuleVol: ' + errorMessage, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception");
443 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage);
444 execution.setVariable("WorkflowException", exception);
446 msoLogger.trace('Exited ' + method)
447 msoLogger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)