Containerization feature of SO
[so.git] / bpmn / so-bpmn-infrastructure-flows / src / main / groovy / org / onap / so / 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.onap.so.bpmn.infrastructure.scripts
22
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.logger.MessageEnum
33 import org.onap.so.logger.MsoLogger
34 import org.onap.so.rest.APIResponse
35 import org.springframework.web.util.UriUtils
36
37 class UpdateVfModuleVolume extends VfModuleBase {
38         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, UpdateVfModuleVolume.class);
39         
40         ExceptionUtil exceptionUtil = new ExceptionUtil()
41
42         /**
43          * Initialize the flow's variables.
44          *
45          * @param execution The flow's execution instance.
46          */
47         private void initProcessVariables(DelegateExecution execution) {
48                 execution.setVariable('prefix', 'UPDVfModVol_')
49                 execution.setVariable('UPDVfModVol_Request', null)
50                 execution.setVariable('UPDVfModVol_requestInfo', null)
51                 execution.setVariable('UPDVfModVol_requestId', null)
52                 execution.setVariable('UPDVfModVol_source', null)
53                 execution.setVariable('UPDVfModVol_volumeInputs', null)
54                 execution.setVariable('UPDVfModVol_volumeGroupId', null)
55                 execution.setVariable('UPDVfModVol_vnfType', null)
56                 execution.setVariable('UPDVfModVol_serviceId', null)
57                 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
58                 execution.setVariable('UPDVfModVol_tenantId', null)
59                 execution.setVariable('UPDVfModVol_volumeParams', null)
60                 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
61                 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
62                 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
63         }
64
65         /**
66          * Check for missing elements in the received request.
67          *
68          * @param execution The flow's execution instance.
69          */
70         @Override
71         public void preProcessRequest(DelegateExecution execution) {
72                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
73                         'execution=' + execution.getId() +
74                         ')'
75
76                 msoLogger.trace('Entered ' + method)
77
78                 try {
79                         initProcessVariables(execution)
80                         String request = validateRequest(execution)
81
82                         def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
83                         execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
84                         execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
85                         execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
86
87                         def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
88                         execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
89                         execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
90                         execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
91                         execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
92                         execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
93                         execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
94
95                         def volumeParams = utils.getNodeXml(request, 'volume-params')
96                         execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
97
98                         msoLogger.trace('Exited ' + method)
99                         msoLogger.debug("UpdateVfModuleVolume request: " + request)
100                 } catch (BpmnError bpmnError) {
101                         throw bpmnError
102                 } catch (Exception e) {
103                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
104                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
105                 }
106         }
107
108         /**
109          * Prepare and send the synchronous response.
110          *
111          * @param execution The flow's execution instance.
112          */
113         public void sendSynchResponse(DelegateExecution execution) {
114                 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
115                         'execution=' + execution.getId() +
116                         ')'
117
118                 msoLogger.trace('Entered ' + method)
119
120                 try {
121                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
122                         def requestId = execution.getVariable('UPDVfModVol_requestId')
123                         def source = execution.getVariable('UPDVfModVol_source')
124                         def progress = getNodeTextForce(requestInfo, 'progress')
125                         if (progress.isEmpty()) {
126                                 progress = '0'
127                         }
128                         def startTime = getNodeTextForce(requestInfo, 'start-time')
129                         if (startTime.isEmpty()) {
130                                 startTime = System.currentTimeMillis()
131                         }
132                         def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
133
134                         String synchResponse = """
135                                 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
136                                         <request-info>
137                                                 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
138                                                 <action>UPDATE_VF_MODULE_VOL</action>
139                                                 <request-status>IN_PROGRESS</request-status>
140                                                 <progress>${MsoUtils.xmlEscape(progress)}</progress>
141                                                 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
142                                                 <source>${MsoUtils.xmlEscape(source)}</source>
143                                         </request-info>
144                                         ${volumeInputs}
145                                 </volume-request>
146                         """
147
148                         synchResponse = utils.formatXml(synchResponse)
149                         sendWorkflowResponse(execution, 200, synchResponse)
150                         msoLogger.debug("UpdateVfModuleVolume Synch Response: " + synchResponse)
151                 } catch (BpmnError e) {
152                         throw e;
153                 } catch (Exception e) {
154                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
155                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
156                 }
157         }
158
159         /**
160          * Prepare a Request for querying AAI for Volume Group information using the
161          * Volume Group Id and Aic Cloud Region.
162          *
163          * @param execution The flow's execution instance.
164          */
165         public void queryAAIForVolumeGroup(DelegateExecution execution) {
166                 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
167                         'execution=' + execution.getId() +
168                         ')'
169
170                 msoLogger.trace('Entered ' + method)
171
172                 try {
173                         def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
174                         def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
175                         def endPoint = UrnPropertiesReader.getVariable("aai.endpoint", execution) +
176                                 '/aai/v7/cloud-infrastructure/cloud-regions/cloud-region/att-aic/' + UriUtils.encode(aicCloudRegion, "UTF-8") +
177                                 '/volume-groups/volume-group/' + UriUtils.encode(volumeGroupId, "UTF-8")
178
179                         msoLogger.debug('Sending GET to AAI endpoint \'' + endPoint + '\'')
180                         msoLogger.debug("UpdateVfModuleVolume sending GET for quering AAI endpoint: " + endPoint)
181
182                         AaiUtil aaiUtil = new AaiUtil(this)
183                         APIResponse response = aaiUtil.executeAAIGetCall(execution, endPoint)
184                         def int statusCode = response.getStatusCode()
185                         def responseData = response.getResponseBodyAsString()
186                         msoLogger.debug('Response code:' + statusCode)
187                         msoLogger.debug('Response:' + System.lineSeparator() + responseData)
188                         msoLogger.debug("UpdateVfModuleVolume response data: " + responseData)
189
190                         def volumeGroup = responseData
191                         def heatStackId = getNodeTextForce(volumeGroup, 'heat-stack-id')
192                         execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
193                         if ((statusCode == 200) || (statusCode == 204)) {
194                                 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroup)
195                                 if (volumeGroupTenantId == null) {
196                                         throw new Exception('Could not find Tenant Id element in Volume Group with Volume Group Id \'' + volumeGroupId + '\''
197                                                 + '\', AIC Cloud Region \'' + aicCloudRegion + '\'')
198                                 }
199                                 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
200                                 msoLogger.debug('Received Tenant Id \'' + volumeGroupTenantId + '\' from AAI for Volume Group with Volume Group Id \'' + volumeGroupId + '\''
201                                         + '\', AIC Cloud Region \'' + aicCloudRegion + '\'')
202                         } else if (statusCode == 404) {
203                                 throw new Exception('Volume Group \'' + volumeGroupId + '\' not found at AAI')
204                         } else {
205                                 throw new Exception('Bad status code ' + statusCode + ' received from AAI; Response data: ' + responseData)
206                         }
207
208                         msoLogger.trace('Exited ' + method)
209                 } catch (BpmnError e) {
210                         throw e;
211                 } catch (Exception e) {
212                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
213                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
214                 }
215         }
216
217         /**
218          * Prepare a Request for invoking the VnfAdapterRest subflow to do
219          * a Volume Group update.
220          *
221          * @param execution The flow's execution instance.
222          */
223         public void prepVnfAdapterRest(DelegateExecution execution) {
224                 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
225                         'execution=' + execution.getId() +
226                         ')'
227
228                 msoLogger.trace('Entered ' + method)
229
230                 try {
231                         def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
232                         def tenantId = execution.getVariable('UPDVfModVol_tenantId')
233                         def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
234                         def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
235                         def vnfType = execution.getVariable('UPDVfModVol_vnfType')
236
237                         def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
238                         def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
239
240                         def requestId = execution.getVariable('UPDVfModVol_requestId')
241                         def serviceId = execution.getVariable('UPDVfModVol_serviceId')
242
243                         def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
244                         def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
245                         def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution)
246                         if ('true'.equals(useQualifiedHostName)) {
247                                         notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
248                         }
249
250                         String vnfAdapterRestRequest = """
251                                 <updateVolumeGroupRequest>
252                                         <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
253                                         <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
254                                         <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
255                                         <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
256                                         <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
257                                         <vnfVersion></vnfVersion>
258                                         <vfModuleType></vfModuleType>
259                                         <volumeGroupParams>
260                                                 ${volumeGroupParams}
261                                     </volumeGroupParams>
262                                         <skipAAI>true</skipAAI>
263                                     <msoRequest>
264                                         <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
265                                         <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
266                                     </msoRequest>
267                                     <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
268                                     <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
269                                 </updateVolumeGroupRequest>
270                         """
271                         vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
272                         execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
273                         msoLogger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
274
275                         msoLogger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: " + vnfAdapterRestRequest)
276                         msoLogger.trace('Exited ' + method)
277                 } catch (BpmnError e) {
278                         throw e;
279                 } catch (Exception e) {
280                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
281                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
282                 }
283         }
284
285         /**
286          * Prepare a Request for updating the DB for this Infra request.
287          *
288          * @param execution The flow's execution instance.
289          */
290         public void prepDbInfraDbRequest(DelegateExecution execution) {
291                 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
292                         'execution=' + execution.getId() +
293                         ')'
294
295                 msoLogger.trace('Entered ' + method)
296
297                 try {
298                         def requestId = execution.getVariable('UPDVfMod_requestId')
299
300                         String updateInfraRequest = """
301                                 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
302                                                 xmlns:req="http://org.onap.so/requestsdb">
303                                         <soapenv:Header/>
304                                         <soapenv:Body>
305                                                 <req:updateInfraRequest>
306                                                         <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
307                                                         <lastModifiedBy>BPEL</lastModifiedBy>
308                                                         <requestStatus>COMPLETE</requestStatus>
309                                                         <progress>100</progress>
310                                                 </req:updateInfraRequest>
311                                         </soapenv:Body>
312                                 </soapenv:Envelope>
313                         """
314
315                         updateInfraRequest = utils.formatXml(updateInfraRequest)
316                         execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
317                         msoLogger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
318
319                         msoLogger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: " + updateInfraRequest)
320                         msoLogger.trace('Exited ' + method)
321                 } catch (BpmnError e) {
322                         throw e;
323                 } catch (Exception e) {
324                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
325                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
326                 }
327         }
328
329         /**
330          * Build a "CompletionHandler" request.
331          *
332          * @param execution The flow's execution instance.
333          */
334         public void prepCompletionHandlerRequest(DelegateExecution execution) {
335                 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
336                         'execution=' + execution.getId() +
337                         ')'
338
339                 msoLogger.trace('Entered ' + method)
340
341                 try {
342                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
343
344                         String content = """
345                                 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
346                                                 xmlns:reqtype="http://org.onap/so/request/types/v1">
347                                         ${requestInfo}
348                                         <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
349                                 </sdncadapterworkflow:MsoCompletionRequest>
350                         """
351
352                         content = utils.formatXml(content)
353                         msoLogger.debug('Request for Completion Handler:\n' + content)
354                         msoLogger.debug("UpdateVfModuleVolume Completion Handler request: " + content)
355                         execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
356
357                         msoLogger.trace('Exited ' + method)
358                 } catch (BpmnError e) {
359                         throw e;
360                 } catch (Exception e) {
361                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
362                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
363                 }
364         }
365
366         /**
367          * Build a "FalloutHandler" request.
368          *
369          * @param execution The flow's execution instance.
370          */
371         public void prepFalloutHandler(DelegateExecution execution) {
372                 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
373                         'execution=' + execution.getId() +
374                         ')'
375
376                 msoLogger.trace('Entered ' + method)
377
378                 try {
379                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
380
381                         def WorkflowException workflowException = execution.getVariable("WorkflowException")
382                         def errorResponseCode = workflowException.getErrorCode()
383                         def errorResponseMsg = workflowException.getErrorMessage()
384                         def encErrorResponseMsg = ""
385                         if (errorResponseMsg != null) {
386                                 encErrorResponseMsg = errorResponseMsg
387                         }
388
389                         String content = """
390                                 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
391                                                 xmlns:reqtype="http://org.onap/so/request/types/v1"
392                                                 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
393                                                 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
394                                         ${requestInfo}
395                                         <sdncadapterworkflow:WorkflowException>
396                                                 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
397                                                 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
398                                         </sdncadapterworkflow:WorkflowException>
399                                 </sdncadapterworkflow:FalloutHandlerRequest>
400                         """
401                         content = utils.formatXml(content)
402                         msoLogger.debug('Request for Fallout Handler:\n' + content)
403                         msoLogger.debug("UpdateVfModuleVolume Fallout request: " + content)
404                         execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
405
406                         msoLogger.trace('Exited ' + method)
407                 } catch (BpmnError e) {
408                         throw e;
409                 } catch (Exception e) {
410                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Caught exception in ' + method, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception is:\n" + e);
411                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
412                 }
413         }
414
415         /**
416          * Create a WorkflowException for the error case where the Tenant Id from
417          * AAI did not match the Tenant Id in the incoming request.
418          *
419          * @param execution The flow's execution instance.
420          */
421         public void handleTenantIdMismatch(DelegateExecution execution) {
422                 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
423                         'execution=' + execution.getId() +
424                         ')'
425
426                 msoLogger.trace('Entered ' + method)
427
428                 String processKey = getProcessKey(execution);
429                 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
430                 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
431                 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
432                 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
433
434                 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
435                         '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
436
437                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, 'Error in UpdateVfModuleVol: ' + errorMessage, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, "Exception");
438
439                 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage);
440                 execution.setVariable("WorkflowException", exception);
441
442                 msoLogger.trace('Exited ' + method)
443                 msoLogger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)
444         }
445 }