367a63fedeb335248518741eaa1e630a7edb6398
[so.git] / bpmn / so-bpmn-infrastructure-common / 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  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.bpmn.infrastructure.scripts
24
25 import org.apache.commons.collections.CollectionUtils
26 import org.camunda.bpm.engine.delegate.BpmnError
27 import org.camunda.bpm.engine.delegate.DelegateExecution
28 import org.onap.aai.domain.yang.VolumeGroup
29 import org.onap.so.bpmn.common.scripts.ExceptionUtil
30 import org.onap.so.bpmn.common.scripts.MsoUtils
31 import org.onap.so.bpmn.common.scripts.VfModuleBase
32 import org.onap.so.bpmn.core.UrnPropertiesReader
33 import org.onap.so.bpmn.core.WorkflowException
34 import org.onap.so.client.aai.AAIObjectType
35 import org.onap.so.client.aai.entities.AAIResultWrapper
36 import org.onap.so.client.aai.entities.Relationships
37 import org.onap.so.client.aai.entities.uri.AAIResourceUri
38 import org.onap.so.client.aai.entities.uri.AAIUriFactory
39 import org.onap.so.constants.Defaults
40 import org.onap.so.logger.MessageEnum
41 import org.onap.so.logger.MsoLogger
42 import org.slf4j.Logger
43 import org.slf4j.LoggerFactory
44
45 import static org.apache.commons.lang.StringUtils.isEmpty
46
47 class UpdateVfModuleVolume extends VfModuleBase {
48     private static final Logger logger = LoggerFactory.getLogger(UpdateVfModuleVolume.class)
49         
50         ExceptionUtil exceptionUtil = new ExceptionUtil()
51
52         /**
53          * Initialize the flow's variables.
54          *
55          * @param execution The flow's execution instance.
56          */
57         private void initProcessVariables(DelegateExecution execution) {
58                 execution.setVariable('prefix', 'UPDVfModVol_')
59                 execution.setVariable('UPDVfModVol_Request', null)
60                 execution.setVariable('UPDVfModVol_requestInfo', null)
61                 execution.setVariable('UPDVfModVol_requestId', null)
62                 execution.setVariable('UPDVfModVol_source', null)
63                 execution.setVariable('UPDVfModVol_volumeInputs', null)
64                 execution.setVariable('UPDVfModVol_volumeGroupId', null)
65                 execution.setVariable('UPDVfModVol_vnfType', null)
66                 execution.setVariable('UPDVfModVol_serviceId', null)
67                 execution.setVariable('UPDVfModVol_aicCloudRegion', null)
68                 execution.setVariable('UPDVfModVol_tenantId', null)
69                 execution.setVariable('UPDVfModVol_volumeParams', null)
70                 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', null)
71                 execution.setVariable('UPDVfModVol_volumeGroupTenantId', null)
72                 execution.setVariable('UpdateVfModuleVolumeSuccessIndicator', false)
73         }
74
75         /**
76          * Check for missing elements in the received request.
77          *
78          * @param execution The flow's execution instance.
79          */
80         @Override
81         public void preProcessRequest(DelegateExecution execution) {
82                 def method = getClass().getSimpleName() + '.preProcessRequest(' +
83                         'execution=' + execution.getId() +
84                         ')'
85
86         logger.trace('Entered {}', method)
87
88                 try {
89                         initProcessVariables(execution)
90                         String request = validateRequest(execution)
91
92                         def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
93                         execution.setVariable('UPDVfModVol_requestInfo', requestInfo)
94                         execution.setVariable('UPDVfModVol_requestId', getRequiredNodeText(execution, requestInfo, 'request-id'))
95                         execution.setVariable('UPDVfModVol_source', getNodeTextForce(requestInfo, 'source'))
96
97                         def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
98                         execution.setVariable('UPDVfModVol_volumeInputs', volumeInputs)
99                         execution.setVariable('UPDVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
100                         execution.setVariable('UPDVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
101                         execution.setVariable('UPDVfModVol_serviceId', getRequiredNodeText(execution, volumeInputs, 'service-id'))
102                         execution.setVariable('UPDVfModVol_aicCloudRegion', getRequiredNodeText(execution, volumeInputs, 'aic-cloud-region'))
103                         execution.setVariable('UPDVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
104
105                         def volumeParams = utils.getNodeXml(request, 'volume-params')
106                         execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
107
108             logger.trace('Exited {}', method)
109             logger.debug("UpdateVfModuleVolume request: {}", request)
110                 } catch (BpmnError bpmnError) {
111                         throw bpmnError
112                 } catch (Exception e) {
113             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
114                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
115                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in preProcessRequest(): ' + e.getMessage())
116                 }
117         }
118
119         /**
120          * Prepare and send the synchronous response.
121          *
122          * @param execution The flow's execution instance.
123          */
124         public void sendSynchResponse(DelegateExecution execution) {
125                 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
126                         'execution=' + execution.getId() +
127                         ')'
128
129         logger.trace('Entered {}', method)
130
131                 try {
132                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
133                         def requestId = execution.getVariable('UPDVfModVol_requestId')
134                         def source = execution.getVariable('UPDVfModVol_source')
135                         def progress = getNodeTextForce(requestInfo, 'progress')
136                         if (progress.isEmpty()) {
137                                 progress = '0'
138                         }
139                         def startTime = getNodeTextForce(requestInfo, 'start-time')
140                         if (startTime.isEmpty()) {
141                                 startTime = System.currentTimeMillis()
142                         }
143                         def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
144
145                         String synchResponse = """
146                                 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
147                                         <request-info>
148                                                 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
149                                                 <action>UPDATE_VF_MODULE_VOL</action>
150                                                 <request-status>IN_PROGRESS</request-status>
151                                                 <progress>${MsoUtils.xmlEscape(progress)}</progress>
152                                                 <start-time>${MsoUtils.xmlEscape(startTime)}</start-time>
153                                                 <source>${MsoUtils.xmlEscape(source)}</source>
154                                         </request-info>
155                                         ${volumeInputs}
156                                 </volume-request>
157                         """
158
159                         synchResponse = utils.formatXml(synchResponse)
160                         sendWorkflowResponse(execution, 200, synchResponse)
161             logger.debug("UpdateVfModuleVolume Synch Response: {}", synchResponse)
162                 } catch (BpmnError e) {
163                         throw e
164                 } catch (Exception e) {
165             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
166                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
167                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in sendSynchResponse(): ' + e.getMessage())
168                 }
169         }
170
171         /**
172          * Prepare a Request for querying AAI for Volume Group information using the
173          * Volume Group Id and Aic Cloud Region.
174          *
175          * @param execution The flow's execution instance.
176          */
177         public void queryAAIForVolumeGroup(DelegateExecution execution) {
178                 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
179                         'execution=' + execution.getId() +
180                         ')'
181
182         logger.trace('Entered {}', method)
183
184                 try {
185                         def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
186                         def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
187                         AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(),aicCloudRegion,volumeGroupId)
188                         AAIResultWrapper wrapper =  getAAIClient().get(uri)
189                         Optional<VolumeGroup> volumeGroup = wrapper.asBean(VolumeGroup.class)
190                         if(volumeGroup.isPresent()){
191                                 def heatStackId = volumeGroup.get().getHeatStackId()
192                                 execution.setVariable('UPDVfModVol_volumeGroupHeatStackId', heatStackId)
193                                 Optional<Relationships> relationships = wrapper.getRelationships()
194                                 if(relationships.isPresent()){
195                                         List<AAIResourceUri> resourceUriList = relationships.get().getRelatedAAIUris(AAIObjectType.TENANT)
196                                         if(CollectionUtils.isNotEmpty(resourceUriList)){
197                                                 AAIResourceUri tenantUri = resourceUriList.get(0)
198                                                 String volumeGroupTenantId = tenantUri.getURIKeys().get("tenant-id")
199                                                 if( isEmpty(volumeGroupTenantId)){
200                                                         exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
201                                                 }
202                                                 execution.setVariable('UPDVfModVol_volumeGroupTenantId', volumeGroupTenantId)
203                         logger.debug("Received Tenant Id: {} from AAI for Volume Group with Volume Group Id: {}, AIC Cloud Region",
204                                 volumeGroupTenantId, volumeGroupId, aicCloudRegion)
205                                         }else{
206                                                 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
207                                         }
208                                 }
209                         }else{
210                                 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Volume Group" + volumeGroupId + " not found at AAI")
211                         }
212             logger.trace('Exited {}', method)
213                 } catch (BpmnError e) {
214                         throw e
215                 } catch (Exception e) {
216             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
217                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
218                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in queryAAIForVolumeGroup(): ' + e.getMessage())
219                 }
220         }
221
222         /**
223          * Prepare a Request for invoking the VnfAdapterRest subflow to do
224          * a Volume Group update.
225          *
226          * @param execution The flow's execution instance.
227          */
228         public void prepVnfAdapterRest(DelegateExecution execution) {
229                 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
230                         'execution=' + execution.getId() +
231                         ')'
232
233         logger.trace('Entered {}', method)
234
235                 try {
236                         def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
237                         def tenantId = execution.getVariable('UPDVfModVol_tenantId')
238                         def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
239                         def volumeGroupHeatStackId = execution.getVariable('UPDVfModVol_volumeGroupHeatStackId')
240                         def vnfType = execution.getVariable('UPDVfModVol_vnfType')
241
242                         def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
243                         def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
244
245                         def requestId = execution.getVariable('UPDVfModVol_requestId')
246                         def serviceId = execution.getVariable('UPDVfModVol_serviceId')
247
248                         def messageId = execution.getVariable('mso-request-id') + '-' + System.currentTimeMillis()
249                         def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
250                         def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host",execution)
251                         if ('true'.equals(useQualifiedHostName)) {
252                                         notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
253                         }
254
255                         String vnfAdapterRestRequest = """
256                                 <updateVolumeGroupRequest>
257                                         <cloudSiteId>${MsoUtils.xmlEscape(aicCloudRegion)}</cloudSiteId>
258                                         <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
259                                         <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
260                                         <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
261                                         <vnfType>${MsoUtils.xmlEscape(vnfType)}</vnfType>
262                                         <vnfVersion></vnfVersion>
263                                         <vfModuleType></vfModuleType>
264                                         <volumeGroupParams>
265                                                 ${volumeGroupParams}
266                                     </volumeGroupParams>
267                                         <skipAAI>true</skipAAI>
268                                     <msoRequest>
269                                         <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
270                                         <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
271                                     </msoRequest>
272                                     <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
273                                     <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
274                                 </updateVolumeGroupRequest>
275                         """
276                         vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
277                         execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
278             logger.debug('Request for VNFAdapter Rest:\n{}', vnfAdapterRestRequest)
279
280             logger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: {}", vnfAdapterRestRequest)
281             logger.trace('Exited {}', method)
282                 } catch (BpmnError e) {
283                         throw e
284                 } catch (Exception e) {
285             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
286                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
287                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepVnfAdapterRest(): ' + e.getMessage())
288                 }
289         }
290
291         /**
292          * Prepare a Request for updating the DB for this Infra request.
293          *
294          * @param execution The flow's execution instance.
295          */
296         public void prepDbInfraDbRequest(DelegateExecution execution) {
297                 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
298                         'execution=' + execution.getId() +
299                         ')'
300
301         logger.trace('Entered {}', method)
302
303                 try {
304                         def requestId = execution.getVariable('UPDVfMod_requestId')
305
306                         String updateInfraRequest = """
307                                 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
308                                                 xmlns:req="http://org.onap.so/requestsdb">
309                                         <soapenv:Header/>
310                                         <soapenv:Body>
311                                                 <req:updateInfraRequest>
312                                                         <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
313                                                         <lastModifiedBy>BPEL</lastModifiedBy>
314                                                         <requestStatus>COMPLETE</requestStatus>
315                                                         <progress>100</progress>
316                                                 </req:updateInfraRequest>
317                                         </soapenv:Body>
318                                 </soapenv:Envelope>
319                         """
320
321                         updateInfraRequest = utils.formatXml(updateInfraRequest)
322                         execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
323             logger.debug('Request for Update Infra Request:\n{}', updateInfraRequest)
324
325             logger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: {}", updateInfraRequest)
326             logger.trace('Exited {}', method)
327                 } catch (BpmnError e) {
328                         throw e
329                 } catch (Exception e) {
330             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
331                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
332                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepDbInfraDbRequest(): ' + e.getMessage())
333                 }
334         }
335
336         /**
337          * Build a "CompletionHandler" request.
338          *
339          * @param execution The flow's execution instance.
340          */
341         public void prepCompletionHandlerRequest(DelegateExecution execution) {
342                 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
343                         'execution=' + execution.getId() +
344                         ')'
345
346         logger.trace('Entered {}', method)
347
348                 try {
349                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
350
351                         String content = """
352                                 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
353                                                 xmlns:reqtype="http://org.onap/so/request/types/v1">
354                                         ${requestInfo}
355                                         <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
356                                 </sdncadapterworkflow:MsoCompletionRequest>
357                         """
358
359                         content = utils.formatXml(content)
360             logger.debug('Request for Completion Handler:\n{}', content)
361             logger.debug("UpdateVfModuleVolume Completion Handler request: {}", content)
362                         execution.setVariable('UPDVfModVol_CompletionHandlerRequest', content)
363
364             logger.trace('Exited {}', method)
365                 } catch (BpmnError e) {
366                         throw e
367                 } catch (Exception e) {
368             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
369                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
370                         exceptionUtil.buildAndThrowWorkflowException(execution, 1002, 'Error in prepCompletionHandlerRequest(): ' + e.getMessage())
371                 }
372         }
373
374         /**
375          * Build a "FalloutHandler" request.
376          *
377          * @param execution The flow's execution instance.
378          */
379         public void prepFalloutHandler(DelegateExecution execution) {
380                 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
381                         'execution=' + execution.getId() +
382                         ')'
383
384         logger.trace('Entered {}', method)
385
386                 try {
387                         def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
388
389                         def WorkflowException workflowException = execution.getVariable("WorkflowException")
390                         def errorResponseCode = workflowException.getErrorCode()
391                         def errorResponseMsg = workflowException.getErrorMessage()
392                         def encErrorResponseMsg = ""
393                         if (errorResponseMsg != null) {
394                                 encErrorResponseMsg = errorResponseMsg
395                         }
396
397                         String content = """
398                                 <sdncadapterworkflow:FalloutHandlerRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
399                                                 xmlns:reqtype="http://org.onap/so/request/types/v1"
400                                                 xmlns:msoservtypes="http://org.onap/so/request/types/v1"
401                                                 xmlns:structuredtypes="http://org.onap/so/structured/types/v1">
402                                         ${requestInfo}
403                                         <sdncadapterworkflow:WorkflowException>
404                                                 <sdncadapterworkflow:ErrorMessage>${MsoUtils.xmlEscape(encErrorResponseMsg)}</sdncadapterworkflow:ErrorMessage>
405                                                 <sdncadapterworkflow:ErrorCode>${MsoUtils.xmlEscape(errorResponseCode)}</sdncadapterworkflow:ErrorCode>
406                                         </sdncadapterworkflow:WorkflowException>
407                                 </sdncadapterworkflow:FalloutHandlerRequest>
408                         """
409                         content = utils.formatXml(content)
410             logger.debug('Request for Fallout Handler:\n{}', content)
411             logger.debug("UpdateVfModuleVolume Fallout request: {}", content)
412                         execution.setVariable('UPDVfModVol_FalloutHandlerRequest', content)
413
414             logger.trace('Exited {}', method)
415                 } catch (BpmnError e) {
416                         throw e
417                 } catch (Exception e) {
418             logger.error("{} {} Caught exception in {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
419                     MsoLogger.ErrorCode.UnknownError.getValue(), method, e)
420                         exceptionUtil.buildWorkflowException(execution, 1002, 'Error in prepFalloutHandler(): ' + e.getMessage())
421                 }
422         }
423
424         /**
425          * Create a WorkflowException for the error case where the Tenant Id from
426          * AAI did not match the Tenant Id in the incoming request.
427          *
428          * @param execution The flow's execution instance.
429          */
430         public void handleTenantIdMismatch(DelegateExecution execution) {
431                 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
432                         'execution=' + execution.getId() +
433                         ')'
434
435         logger.trace('Entered {}', method)
436
437                 String processKey = getProcessKey(execution)
438                 def volumeGroupId = execution.getVariable('UPDVfModVol_volumeGroupId')
439                 def aicCloudRegion = execution.getVariable('UPDVfModVol_aicCloudRegion')
440                 def tenantId = execution.getVariable('UPDVfModVol_tenantId')
441                 def volumeGroupTenantId = execution.getVariable('UPDVfModVol_volumeGroupTenantId')
442
443                 def String errorMessage = 'TenantId \'' + tenantId + '\' in incoming request does not match Tenant Id \'' + volumeGroupTenantId +
444                         '\' retrieved from AAI for Volume Group Id \'' + volumeGroupId + '\', AIC Cloud Region \'' + aicCloudRegion + '\''
445
446                 logger.error("{} {} Error in UpdateVfModuleVol: {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
447                 MsoLogger.ErrorCode.UnknownError.getValue(), errorMessage)
448
449                 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage)
450                 execution.setVariable("WorkflowException", exception)
451
452                 logger.trace('Exited ' + method)
453                 logger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)
454         }
455 }