Groovy scripts header correction
[so.git] / bpmn / MSOInfrastructureBPMN / src / main / groovy / org / openecomp / mso / bpmn / infrastructure / scripts / UpdateVfModuleVolume.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.openecomp.mso.bpmn.infrastructure.scripts
22
23 import java.util.concurrent.ExecutionException;
24
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
35
36 class UpdateVfModuleVolume extends VfModuleBase {
37
38         ExceptionUtil exceptionUtil = new ExceptionUtil()
39
40         /**
41          * Initialize the flow's variables.
42          *
43          * @param execution The flow's execution instance.
44          */
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)
61         }
62
63         /**
64          * Check for missing elements in the received request.
65          *
66          * @param execution The flow's execution instance.
67          */
68         @Override
69         public void preProcessRequest(Execution execution) {
70                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
71                         'execution=' + execution.getId() +
72                         ')'
73                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
74                 logDebug('Entered ' + method, isDebugLogEnabled)
75
76                 try {
77                         initProcessVariables(execution)
78                         String request = validateRequest(execution)
79
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'))
84
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'))
92
93                         def volumeParams = utils.getNodeXml(request, 'volume-params')
94                         execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
95
96                         logDebug('Exited ' + method, isDebugLogEnabled)
97                         utils.logAudit("UpdateVfModuleVolume request: " + request)
98                 } catch (BpmnError bpmnError) {
99                         throw bpmnError
100                 } catch (Exception e) {
101                         logError('Caught exception in ' + method, e)
102                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
103                 }
104         }
105
106         /**
107          * Prepare and send the synchronous response.
108          *
109          * @param execution The flow's execution instance.
110          */
111         public void sendSynchResponse(Execution execution) {
112                 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
113                         'execution=' + execution.getId() +
114                         ')'
115                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
116                 logDebug('Entered ' + method, isDebugLogEnabled)
117
118                 try {
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()) {
124                                 progress = '0'
125                         }
126                         def startTime = getNodeTextForce(requestInfo, 'start-time')
127                         if (startTime.isEmpty()) {
128                                 startTime = System.currentTimeMillis()
129                         }
130                         def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
131
132                         String synchResponse = """
133                                 <volume-request xmlns="http://org.openecomp/mso/infra/vnf-request/v1">
134                                         <request-info>
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>
141                                         </request-info>
142                                         ${volumeInputs}
143                                 </volume-request>
144                         """
145
146                         synchResponse = utils.formatXml(synchResponse)
147                         sendWorkflowResponse(execution, 200, synchResponse)
148                         utils.logAudit("UpdateVfModuleVolume Synch Response: " + synchResponse)
149                 } catch (BpmnError e) {
150                         throw e;
151                 } catch (Exception e) {
152                         logError('Caught exception in ' + method, e)
153                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
154                 }
155         }
156
157         /**
158          * Prepare a Request for querying AAI for Volume Group information using the
159          * Volume Group Id and Aic Cloud Region.
160          *
161          * @param execution The flow's execution instance.
162          */
163         public void queryAAIForVolumeGroup(Execution execution) {
164                 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
165                         'execution=' + execution.getId() +
166                         ')'
167                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
168                 logDebug('Entered ' + method, isDebugLogEnabled)
169
170                 try {
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")
176
177                         logDebug('Sending GET to AAI endpoint \'' + endPoint + '\'', isDebugLogEnabled)
178                         utils.logAudit("UpdateVfModuleVolume sending GET for quering AAI endpoint: " + endPoint)
179
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)
187
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 + '\'')
196                                 }
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')
202                         } else {
203                                 throw new Exception('Bad status code ' + statusCode + ' received from AAI; Response data: ' + responseData)
204                         }
205
206                         logDebug('Exited ' + method, isDebugLogEnabled)
207                 } catch (BpmnError e) {
208                         throw e;
209                 } catch (Exception e) {
210                         logError('Caught exception in ' + method, e)
211                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
212                 }
213         }
214
215         /**
216          * Prepare a Request for invoking the VnfAdapterRest subflow to do
217          * a Volume Group update.
218          *
219          * @param execution The flow's execution instance.
220          */
221         public void prepVnfAdapterRest(Execution execution) {
222                 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
223                         'execution=' + execution.getId() +
224                         ')'
225                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
226                 logDebug('Entered ' + method, isDebugLogEnabled)
227
228                 try {
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')
234
235                         def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
236                         def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
237
238                         def requestId = execution.getVariable('UPDVfModVol_requestId')
239                         def serviceId = execution.getVariable('UPDVfModVol_serviceId')
240
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)
246                         }
247
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>
257                                         <volumeGroupParams>
258                                                 ${volumeGroupParams}
259                                     </volumeGroupParams>
260                                         <skipAAI>true</skipAAI>
261                                     <msoRequest>
262                                         <requestId>${requestId}</requestId>
263                                         <serviceInstanceId>${serviceId}</serviceInstanceId>
264                                     </msoRequest>
265                                     <messageId>${messageId}</messageId>
266                                     <notificationUrl>${notificationUrl}</notificationUrl>
267                                 </updateVolumeGroupRequest>
268                         """
269                         vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
270                         execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
271                         logDebug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest, isDebugLogEnabled)
272
273                         utils.logAudit("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest)
274                         logDebug('Exited ' + method, isDebugLogEnabled)
275                 } catch (BpmnError e) {
276                         throw e;
277                 } catch (Exception e) {
278                         logError('Caught exception in ' + method, e)
279                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
280                 }
281         }
282
283         /**
284          * Prepare a Request for updating the DB for this Infra request.
285          *
286          * @param execution The flow's execution instance.
287          */
288         public void prepDbInfraDbRequest(Execution execution) {
289                 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
290                         'execution=' + execution.getId() +
291                         ')'
292                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
293                 logDebug('Entered ' + method, isDebugLogEnabled)
294
295                 try {
296                         def requestId = execution.getVariable('UPDVfMod_requestId')
297
298                         String updateInfraRequest = """
299                                 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
300                                                 xmlns:req="http://org.openecomp.mso/requestsdb">
301                                         <soapenv:Header/>
302                                         <soapenv:Body>
303                                                 <req:updateInfraRequest>
304                                                         <requestId>${requestId}</requestId>
305                                                         <lastModifiedBy>BPEL</lastModifiedBy>
306                                                         <requestStatus>COMPLETE</requestStatus>
307                                                         <progress>100</progress>
308                                                 </req:updateInfraRequest>
309                                         </soapenv:Body>
310                                 </soapenv:Envelope>
311                         """
312
313                         updateInfraRequest = utils.formatXml(updateInfraRequest)
314                         execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
315                         logDebug('Request for Update Infra Request:\n' + updateInfraRequest, isDebugLogEnabled)
316
317                         utils.logAudit("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest)
318                         logDebug('Exited ' + method, isDebugLogEnabled)
319                 } catch (BpmnError e) {
320                         throw e;
321                 } catch (Exception e) {
322                         logError('Caught exception in ' + method, e)
323                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
324                 }
325         }
326
327         /**
328          * Build a "CompletionHandler" request.
329          *
330          * @param execution The flow's execution instance.
331          */
332         public void prepCompletionHandlerRequest(Execution execution) {
333                 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
334                         'execution=' + execution.getId() +
335                         ')'
336                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
337                 logDebug('Entered ' + method, isDebugLogEnabled)
338
339                 try {
340                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
341
342                         String content = """
343                                 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.openecomp/mso/workflow/schema/v1"
344                                                 xmlns:reqtype="http://org.openecomp/mso/request/types/v1">
345                                         ${requestInfo}
346                                         <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
347                                 </sdncadapterworkflow:MsoCompletionRequest>
348                         """
349
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)
354
355                         logDebug('Exited ' + method, isDebugLogEnabled)
356                 } catch (BpmnError e) {
357                         throw e;
358                 } catch (Exception e) {
359                         logError('Caught exception in ' + method, e)
360                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
361                 }
362         }
363
364         /**
365          * Build a "FalloutHandler" request.
366          *
367          * @param execution The flow's execution instance.
368          */
369         public void prepFalloutHandler(Execution execution) {
370                 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
371                         'execution=' + execution.getId() +
372                         ')'
373                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
374                 logDebug('Entered ' + method, isDebugLogEnabled)
375
376                 try {
377                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
378
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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
385                         }
386
387                         String content = """
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">
392                                         ${requestInfo}
393                                         <sdncadapterworkflow:WorkflowException>
394                                                 <sdncadapterworkflow:ErrorMessage>${encErrorResponseMsg}</sdncadapterworkflow:ErrorMessage>
395                                                 <sdncadapterworkflow:ErrorCode>${errorResponseCode}</sdncadapterworkflow:ErrorCode>
396                                         </sdncadapterworkflow:WorkflowException>
397                                 </sdncadapterworkflow:FalloutHandlerRequest>
398                         """
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)
403
404                         logDebug('Exited ' + method, isDebugLogEnabled)
405                 } catch (BpmnError e) {
406                         throw e;
407                 } catch (Exception e) {
408                         logError('Caught exception in ' + method, e)
409                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
410                 }
411         }
412
413         /**
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.
416          *
417          * @param execution The flow's execution instance.
418          */
419         public void handleTenantIdMismatch(Execution execution) {
420                 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
421                         'execution=' + execution.getId() +
422                         ')'
423                 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
424                 logDebug('Entered ' + method, isDebugLogEnabled)
425
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')
431
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 + '\''
434
435                 logError('Error in UpdateVfModuleVol: ' + errorMessage)
436
437                 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage);
438                 execution.setVariable("WorkflowException", exception);
439
440                 logDebug('Exited ' + method, isDebugLogEnabled)
441                 utils.logAudit("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)
442         }
443 }