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.openecomp.mso.bpmn.infrastructure.scripts
23 import java.util.concurrent.ExecutionException;
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.runtime.Execution
27 import org.apache.commons.lang3.*
28 import org.springframework.web.util.UriUtils
29 import org.openecomp.mso.bpmn.common.scripts.AaiUtil
30 import org.openecomp.mso.bpmn.common.scripts.VfModuleBase
31 import org.openecomp.mso.bpmn.core.WorkflowException
32 import org.openecomp.mso.bpmn.core.json.JsonUtils;
33 import org.openecomp.mso.rest.APIResponse
34 import org.openecomp.mso.bpmn.common.scripts.ExceptionUtil
36 class UpdateVfModuleVolume extends VfModuleBase {
38 ExceptionUtil exceptionUtil = new ExceptionUtil()
41 * Initialize the flow's variables.
43 * @param execution The flow's execution instance.
45 private void initProcessVariables(Execution execution) {
46 execution.setVariable('prefix', 'UPDVfModVol_')
47 execution.setVariable('UPDVfModVol_Request', null)
48 execution.setVariable('UPDVfModVol_requestInfo', null)
49 execution.setVariable('UPDVfModVol_requestId', null)
50 execution.setVariable('UPDVfModVol_source', null)
51 execution.setVariable('UPDVfModVol_volumeInputs', null)
52 execution.setVariable('UPDVfModVol_volumeGroupId', null)
53 execution.setVariable('UPDVfModVol_vnfType', null)
54 execution.setVariable('UPDVfModVol_serviceId', null)
55 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
56 execution.setVariable('UPDVfModVol_tenantId', null)
57 execution.setVariable('UPDVfModVol_volumeParams', null)
58 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
59 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
60 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
64 * Check for missing elements in the received request.
66 * @param execution The flow's execution instance.
69 public void preProcessRequest(Execution execution) {
70 def method = getClass().getSimpleName() + '.preProcessRequest(' +
71 'execution=' + execution.getId() +
73 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
74 logDebug('Entered ' + method, isDebugLogEnabled)
77 initProcessVariables(execution)
78 String request = validateRequest(execution)
80 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
81 execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
82 execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
83 execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
85 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
86 execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
87 execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
88 execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
89 execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
90 execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
91 execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
93 def volumeParams = utils.getNodeXml(request, 'volume-params')
94 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
96 logDebug('Exited ' + method, isDebugLogEnabled)
97 utils.logAudit("UpdateVfModuleVolume request: " + request)
98 } catch (BpmnError bpmnError) {
100 } catch (Exception e) {
101 logError('Caught exception in ' + method, e)
102 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
107 * Prepare and send the synchronous response.
109 * @param execution The flow's execution instance.
111 public void sendSynchResponse(Execution execution) {
112 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
113 'execution=' + execution.getId() +
115 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
116 logDebug('Entered ' + method, isDebugLogEnabled)
119 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
120 def requestId = execution.getVariable('UPDVfModVol_requestId')
121 def source = execution.getVariable('UPDVfModVol_source')
122 def progress = getNodeTextForce(requestInfo, 'progress')
123 if (progress.isEmpty()) {
126 def startTime = getNodeTextForce(requestInfo, 'start-time')
127 if (startTime.isEmpty()) {
128 startTime = System.currentTimeMillis()
130 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
132 String synchResponse = """
133 <volume-request xmlns="http://org.openecomp/mso/infra/vnf-request/v1">
135 <request-id>${requestId}</request-id>
136 <action>UPDATE_VF_MODULE_VOL</action>
137 <request-status>IN_PROGRESS</request-status>
138 <progress>${progress}</progress>
139 <start-time>${startTime}</start-time>
140 <source>${source}</source>
146 synchResponse = utils.formatXml(synchResponse)
147 sendWorkflowResponse(execution, 200, synchResponse)
148 utils.logAudit("UpdateVfModuleVolume Synch Response: " + synchResponse)
149 } catch (BpmnError e) {
151 } catch (Exception e) {
152 logError('Caught exception in ' + method, e)
153 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
158 * Prepare a Request for querying AAI for Volume Group information using the
159 * Volume Group Id and Aic Cloud Region.
161 * @param execution The flow's execution instance.
163 public void queryAAIForVolumeGroup(Execution execution) {
164 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
165 'execution=' + execution.getId() +
167 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
168 logDebug('Entered ' + method, isDebugLogEnabled)
171 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
172 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
173 def endPoint = execution.getVariable('URN_aai_endpoint') +
174 '/aai/v7/cloud-infrastructure/cloud-regions/cloud-region/att-aic/' + UriUtils.encode(aicCloudRegion, "UTF-8") +
175 '/volume-groups/volume-group/' + UriUtils.encode(volumeGroupId, "UTF-8")
177 logDebug('Sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
178 utils.logAudit("UpdateVfModuleVolume sending GET for quering AAI endpoint: " + endPoint)
180 AaiUtil aaiUtil = new AaiUtil(this)
181 APIResponse response = aaiUtil.executeAAIGetCall(execution, endPoint)
182 def int statusCode = response.getStatusCode()
183 def responseData = response.getResponseBodyAsString()
184 logDebug('Response code:' + statusCode, isDebugLogEnabled)
185 logDebug('Response:' + System.lineSeparator() + responseData, isDebugLogEnabled)
186 utils.logAudit("UpdateVfModuleVolume response data: " + responseData)
188 def volumeGroup = responseData
189 def heatStackId = getNodeTextForce(volumeGroup, 'heat-stack-id')
190 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
191 if ((statusCode == 200) || (statusCode == 204)) {
192 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroup)
193 if (volumeGroupTenantId == null) {
194 throw new Exception('Could not find Tenant Id element in Volume Group with Volume Group Id \'' + volumeGroupId + '\''
195 + '\', AIC Cloud Region \'' + aicCloudRegion + '\'')
197 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
198 logDebug('Received Tenant Id \'' + volumeGroupTenantId + '\' from AAI for Volume Group with Volume Group Id \'' + volumeGroupId + '\''
199 + '\', AIC Cloud Region \'' + aicCloudRegion + '\'', isDebugLogEnabled)
200 } else if (statusCode == 404) {
201 throw new Exception('Volume Group \'' + volumeGroupId + '\' not found at AAI')
203 throw new Exception('Bad status code ' + statusCode + ' received from AAI; Response data: ' + responseData)
206 logDebug('Exited ' + method, isDebugLogEnabled)
207 } catch (BpmnError e) {
209 } catch (Exception e) {
210 logError('Caught exception in ' + method, e)
211 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
216 * Prepare a Request for invoking the VnfAdapterRest subflow to do
217 * a Volume Group update.
219 * @param execution The flow's execution instance.
221 public void prepVnfAdapterRest(Execution execution) {
222 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
223 'execution=' + execution.getId() +
225 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
226 logDebug('Entered ' + method, isDebugLogEnabled)
229 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
230 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
231 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
232 def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
233 def vnfType = execution.getVariable('UPDVfModVol_vnfType')
235 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
236 def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
238 def requestId = execution.getVariable('UPDVfModVol_requestId')
239 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
241 def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
242 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
243 def useQualifiedHostName = execution.getVariable("URN_mso_use_qualified_host")
244 if ('true'.equals(useQualifiedHostName)) {
245 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
248 String vnfAdapterRestRequest = """
249 <updateVolumeGroupRequest>
250 <cloudSiteId>${aicCloudRegion}</cloudSiteId>
251 <tenantId>${tenantId}</tenantId>
252 <volumeGroupId>${volumeGroupId}</volumeGroupId>
253 <volumeGroupStackId>${volumeGroupHeatStackId}</volumeGroupStackId>
254 <vnfType>${vnfType}</vnfType>
255 <vnfVersion></vnfVersion>
256 <vfModuleType></vfModuleType>
260 <skipAAI>true</skipAAI>
262 <requestId>${requestId}</requestId>
263 <serviceInstanceId>${serviceId}</serviceInstanceId>
265 <messageId>${messageId}</messageId>
266 <notificationUrl>${notificationUrl}</notificationUrl>
267 </updateVolumeGroupRequest>
269 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
270 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
271 logDebug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest, isDebugLogEnabled)
273 utils.logAudit("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest)
274 logDebug('Exited ' + method, isDebugLogEnabled)
275 } catch (BpmnError e) {
277 } catch (Exception e) {
278 logError('Caught exception in ' + method, e)
279 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
284 * Prepare a Request for updating the DB for this Infra request.
286 * @param execution The flow's execution instance.
288 public void prepDbInfraDbRequest(Execution execution) {
289 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
290 'execution=' + execution.getId() +
292 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
293 logDebug('Entered ' + method, isDebugLogEnabled)
296 def requestId = execution.getVariable('UPDVfMod_requestId')
298 String updateInfraRequest = """
299 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
300 xmlns:req="http://org.openecomp.mso/requestsdb">
303 <req:updateInfraRequest>
304 <requestId>${requestId}</requestId>
305 <lastModifiedBy>BPEL</lastModifiedBy>
306 <requestStatus>COMPLETE</requestStatus>
307 <progress>100</progress>
308 </req:updateInfraRequest>
313 updateInfraRequest = utils.formatXml(updateInfraRequest)
314 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
315 logDebug('Request for Update Infra Request:\n' + updateInfraRequest, isDebugLogEnabled)
317 utils.logAudit("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest)
318 logDebug('Exited ' + method, isDebugLogEnabled)
319 } catch (BpmnError e) {
321 } catch (Exception e) {
322 logError('Caught exception in ' + method, e)
323 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
328 * Build a "CompletionHandler" request.
330 * @param execution The flow's execution instance.
332 public void prepCompletionHandlerRequest(Execution execution) {
333 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
334 'execution=' + execution.getId() +
336 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
337 logDebug('Entered ' + method, isDebugLogEnabled)
340 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
343 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.openecomp/mso/workflow/schema/v1"
344 xmlns:reqtype="http://org.openecomp/mso/request/types/v1">
346 <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
347 </sdncadapterworkflow:MsoCompletionRequest>
350 content = utils.formatXml(content)
351 logDebug('Request for Completion Handler:\n' + content, isDebugLogEnabled)
352 utils.logAudit("UpdateVfModuleVolume Completion Handler request: " + content)
353 execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
355 logDebug('Exited ' + method, isDebugLogEnabled)
356 } catch (BpmnError e) {
358 } catch (Exception e) {
359 logError('Caught exception in ' + method, e)
360 exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
365 * Build a "FalloutHandler" request.
367 * @param execution The flow's execution instance.
369 public void prepFalloutHandler(Execution execution) {
370 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
371 'execution=' + execution.getId() +
373 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
374 logDebug('Entered ' + method, isDebugLogEnabled)
377 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
379 def WorkflowException workflowException = execution.getVariable("WorkflowException")
380 def errorResponseCode = workflowException.getErrorCode()
381 def errorResponseMsg = workflowException.getErrorMessage()
382 def encErrorResponseMsg = ""
383 if (errorResponseMsg != null) {
384 encErrorResponseMsg = errorResponseMsg.replace("&", "&").replace("<", "<").replace(">", ">")
388 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.openecomp/mso/workflow/schema/v1"
389 xmlns:reqtype="http://org.openecomp/mso/request/types/v1"
390 xmlns:msoservtypes="http://org.openecomp/mso/request/types/v1"
391 xmlns:structuredtypes="http://org.openecomp/mso/structured/types/v1">
393 <sdncadapterworkflow:WorkflowException>
394 <sdncadapterworkflow:ErrorMessage>${encErrorResponseMsg}</sdncadapterworkflow:ErrorMessage>
395 <sdncadapterworkflow:ErrorCode>${errorResponseCode}</sdncadapterworkflow:ErrorCode>
396 </sdncadapterworkflow:WorkflowException>
397 </sdncadapterworkflow:FalloutHandlerRequest>
399 content = utils.formatXml(content)
400 logDebug('Request for Fallout Handler:\n' + content, isDebugLogEnabled)
401 utils.logAudit("UpdateVfModuleVolume Fallout request: " + content)
402 execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
404 logDebug('Exited ' + method, isDebugLogEnabled)
405 } catch (BpmnError e) {
407 } catch (Exception e) {
408 logError('Caught exception in ' + method, e)
409 exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
414 * Create a WorkflowException for the error case where the Tenant Id from
415 * AAI did not match the Tenant Id in the incoming request.
417 * @param execution The flow's execution instance.
419 public void handleTenantIdMismatch(Execution execution) {
420 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
421 'execution=' + execution.getId() +
423 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
424 logDebug('Entered ' + method, isDebugLogEnabled)
426 String processKey = getProcessKey(execution);
427 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
428 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
429 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
430 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
432 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
433 '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
435 logError('Error in UpdateVfModuleVol: ' + errorMessage)
437 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage);
438 execution.setVariable("WorkflowException", exception);
440 logDebug('Exited ' + method, isDebugLogEnabled)
441 utils.logAudit("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)