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