2 * ============LICENSE_START=======================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
23 package org.onap.so.bpmn.infrastructure.scripts
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
47 class UpdateVfModuleVolume extends VfModuleBase {
48 private static final Logger logger = LoggerFactory.getLogger(UpdateVfModuleVolume.class)
50 ExceptionUtil exceptionUtil = new ExceptionUtil()
53 * Initialize the flow's variables.
55 * @param execution The flow's execution instance.
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)
76 * Check for missing elements in the received request.
78 * @param execution The flow's execution instance.
81 public void preProcessRequest(DelegateExecution execution) {
82 def method = getClass().getSimpleName() + '.preProcessRequest(' +
83 'execution=' + execution.getId() +
86 logger.trace('Entered {}', method)
89 initProcessVariables(execution)
90 String request = validateRequest(execution)
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'))
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'))
106 def volumeParams = utils.getNodeXml(request, 'volume-params')
107 execution.setVariable('UPDVfModVol_volumeParams', volumeParams)
109 logger.trace('Exited {}', method)
110 logger.debug("UpdateVfModuleVolume request: {}", request)
111 } catch (BpmnError 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())
121 * Prepare and send the synchronous response.
123 * @param execution The flow's execution instance.
125 public void sendSynchResponse(DelegateExecution execution) {
126 def method = getClass().getSimpleName() + '.sendSynchResponse(' +
127 'execution=' + execution.getId() +
130 logger.trace('Entered {}', method)
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()) {
140 def startTime = getNodeTextForce(requestInfo, 'start-time')
141 if (startTime.isEmpty()) {
142 startTime = System.currentTimeMillis()
144 def volumeInputs = execution.getVariable('UPDVfModVol_volumeInputs')
146 String synchResponse = """
147 <volume-request xmlns="http://org.onap/so/infra/vnf-request/v1">
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>
160 synchResponse = utils.formatXml(synchResponse)
161 sendWorkflowResponse(execution, 200, synchResponse)
162 logger.debug("UpdateVfModuleVolume Synch Response: {}", synchResponse)
163 } catch (BpmnError 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())
173 * Prepare a Request for querying AAI for Volume Group information using the
174 * Volume Group Id and Aic Cloud Region.
176 * @param execution The flow's execution instance.
178 public void queryAAIForVolumeGroup(DelegateExecution execution) {
179 def method = getClass().getSimpleName() + '.queryAAIForVolumeGroup(' +
180 'execution=' + execution.getId() +
183 logger.trace('Entered {}', method)
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)
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)
207 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Could not find Tenant Id element in Volume Group with Volume Group Id" + volumeGroupId + ", AIC Cloud Region" + aicCloudRegion)
211 exceptionUtil.buildAndThrowWorkflowException(execution,2500,"Volume Group" + volumeGroupId + " not found at AAI")
213 logger.trace('Exited {}', method)
214 } catch (BpmnError 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())
224 * Prepare a Request for invoking the VnfAdapterRest subflow to do
225 * a Volume Group update.
227 * @param execution The flow's execution instance.
229 public void prepVnfAdapterRest(DelegateExecution execution) {
230 def method = getClass().getSimpleName() + '.prepVnfAdapterRest(' +
231 'execution=' + execution.getId() +
234 logger.trace('Entered {}', method)
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')
243 def volumeParamsXml = execution.getVariable('UPDVfModVol_volumeParams')
244 def volumeGroupParams = transformParamsToEntries(volumeParamsXml)
246 def requestId = execution.getVariable('UPDVfModVol_requestId')
247 def serviceId = execution.getVariable('UPDVfModVol_serviceId')
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)
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>
269 <skipAAI>true</skipAAI>
271 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
272 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
274 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
275 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
276 </updateVolumeGroupRequest>
278 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
279 execution.setVariable('UPDVfModVol_vnfAdapterRestRequest', vnfAdapterRestRequest)
280 logger.debug('Request for VNFAdapter Rest:\n{}', vnfAdapterRestRequest)
282 logger.debug("UpdateVfModuleVolume Request for VNFAdapter Rest: {}", vnfAdapterRestRequest)
283 logger.trace('Exited {}', method)
284 } catch (BpmnError 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())
294 * Prepare a Request for updating the DB for this Infra request.
296 * @param execution The flow's execution instance.
298 public void prepDbInfraDbRequest(DelegateExecution execution) {
299 def method = getClass().getSimpleName() + '.prepDbInfraDbRequest(' +
300 'execution=' + execution.getId() +
303 logger.trace('Entered {}', method)
306 def requestId = execution.getVariable('UPDVfMod_requestId')
308 String updateInfraRequest = """
309 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
310 xmlns:req="http://org.onap.so/requestsdb">
313 <req:updateInfraRequest>
314 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
315 <lastModifiedBy>BPEL</lastModifiedBy>
316 <requestStatus>COMPLETE</requestStatus>
317 <progress>100</progress>
318 </req:updateInfraRequest>
323 updateInfraRequest = utils.formatXml(updateInfraRequest)
324 execution.setVariable('UPDVfModVol_updateInfraRequest', updateInfraRequest)
325 logger.debug('Request for Update Infra Request:\n{}', updateInfraRequest)
327 logger.debug("UpdateVfModuleVolume Request for Updating DB for Infra: {}", updateInfraRequest)
328 logger.trace('Exited {}', method)
329 } catch (BpmnError 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())
339 * Build a "CompletionHandler" request.
341 * @param execution The flow's execution instance.
343 public void prepCompletionHandlerRequest(DelegateExecution execution) {
344 def method = getClass().getSimpleName() + '.prepCompletionHandlerRequest(' +
345 'execution=' + execution.getId() +
348 logger.trace('Entered {}', method)
351 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
354 <sdncadapterworkflow:MsoCompletionRequest xmlns:sdncadapterworkflow="http://org.onap/so/workflow/schema/v1"
355 xmlns:reqtype="http://org.onap/so/request/types/v1">
357 <sdncadapterworkflow:mso-bpel-name>MSO_ACTIVATE_BPEL</sdncadapterworkflow:mso-bpel-name>
358 </sdncadapterworkflow:MsoCompletionRequest>
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)
366 logger.trace('Exited {}', method)
367 } catch (BpmnError 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())
377 * Build a "FalloutHandler" request.
379 * @param execution The flow's execution instance.
381 public void prepFalloutHandler(DelegateExecution execution) {
382 def method = getClass().getSimpleName() + '.prepFalloutHandler(' +
383 'execution=' + execution.getId() +
386 logger.trace('Entered {}', method)
389 def requestInfo = execution.getVariable('UPDVfModVol_requestInfo')
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
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">
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>
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)
416 logger.trace('Exited {}', method)
417 } catch (BpmnError 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())
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.
430 * @param execution The flow's execution instance.
432 public void handleTenantIdMismatch(DelegateExecution execution) {
433 def method = getClass().getSimpleName() + '.handleTenantIdMismatch(' +
434 'execution=' + execution.getId() +
437 logger.trace('Entered {}', method)
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')
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 + '\''
448 logger.error("{} {} Error in UpdateVfModuleVol: {}\n ", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
449 ErrorCode.UnknownError.getValue(), errorMessage)
451 WorkflowException exception = new WorkflowException(processKey, 5000, errorMessage)
452 execution.setVariable("WorkflowException", exception)
454 logger.trace('Exited ' + method)
455 logger.debug("UpdateVfModuleVolume workflowException in Tenant Mismatch: " + errorMessage)